Posted 22 May 2016 I have a project where I have to read I/O, and potentially initiate programs on the Mitsubishi PLC. Seems I can use the Melsec Protocol but I have some difficulty getting started. I can communicate via Ethernet using GXWorks 2 so hardware-wise there shouldn't be anything wrong. I'm using QJ71E71, Q06HCPU, QX42, etc. Initially I open a UDP socket to the correct IP address and port (copy the port from GXWorks) and attempt to issue a request 3E/Binary, specifying the network, PC, Module IO, and station and it always times out. Is there any source code that just does a basic read of a memory location? I'm using C++ but I should be able to understand any code sample in VB, C, C#, or others. Also, is there any issue with multiple connections to the PLCs. Right now I quit GXWorks before I test but is this necessary. Thanks, Jeff Share this post Link to post Share on other sites
Posted 23 May 2016 The easiest way to talk to a Mitsubishi PLC is to get a license of MX Components, which is a set of protocols and VB functions for talking to Mitsubishi equipment. Unless you are tinkering on your own or developing an OEM application where you plan to duplicate the project on an ongoing basis, the cost of the license pays for itself many times over in time savings. If you are intent on developing the protocol on your own, there are manuals available that detail the Melsec protocol. I have not used it, but I have worked with guys who have. I've never tested multiple connections, so I don't know the answer to that one. Share this post Link to post Share on other sites
Posted 24 May 2016 Thanks for the feedback. I'll take a look at MX Components to see if that can work. My company is an OEM of capital equipment so if it's a per unit license that wouldn't be ideal. Looking at the manuals the Melsec protocol seems simple enough but it would be nice to see a working example to compare my code to. Jeff Share this post Link to post Share on other sites
Posted 24 May 2016 As I understand it, MX Components is a per unit license, so it might make sense to work it out on your own. Depends on the overall cost of the machine and the number of units per year. Can't help you with examples. Share this post Link to post Share on other sites
Posted 1 Jun 2016 Thanks to help from Mark and others I've gotten a little further in that I can get a reply. Unfortunately the reply is always 0x0403, which I found defined as "The number of devices used in the process control instruction is incorrect." Below is my setup. QX42 should be digital input and from GX Works I can see that X21 is high. [Slot] [Type] [Model Name] [Point] [I/OAddress] [CPU] [CPU] [Q06HCPU] [-] [-] [0] [Intelli.] [QJ71E71-100] [32Point] [0000] [1] [Input] [QX42] [64Point] [0020] [2] [Output] [QY42P] [64Point] [0060] [3] [Intelli.] [Q68ADV] [16Point] [00A0] [4] [Intelli.] [Q68DAVN] [16Point] [00B0] [5] [Intelli.] [QD70P8] [32Point] [00C0] To read it I fill in the following structure: request.wFramType = 0x50; //3E request.byNetwork = 1; request.byPC = 255; request.wDestinationModuleIO = 0x20; request.byDestinationModuleStation = 2; request.wDataLength = 12; request.wCPUTimer = 0x10; request.wMainCommand = 0x0401; request.wSubCommand = 0x1; dwAddress = 21; request.abyAddress[0] = reinterpret_cast<BYTE*>(&dwAddress)[0]; request.abyAddress[1] = reinterpret_cast<BYTE*>(&dwAddress)[1]; request.abyAddress[2] = reinterpret_cast<BYTE*>(&dwAddress)[2]; request.eDeviceType = PDT_X; //0x9C request.wSize = 1; I'm not sure what Destination Module IO, Destination Module Station, and Address represent in the structure. Thanks, Jeff Share this post Link to post Share on other sites
Posted 1 Jun 2016 (edited) Destination Module IO would be the I/O addresses used by that module in the CPU/Programming. For example, the input addresses for that module are X20 to X5F (hex). Note that the value of 0x20 matches the I/O address in your configuration setup. Destination Module Station (also called head address) is the rack-bus address of the module, and is the first I/O address with the final digit stripped. So 20 becomes 2. This is generally used for passing data between the CPU and special function modules in ladder logic, but it makes sense it would be used in reading the modules externally. Probably the CPU uses it in the background to R/W the I/O to the CPU, which is transparent when programming the PLC. Not sure about the dwAddress. The request.abyAddress looks to be you grabbing the information from the module. So byte 0 would be X20-X27, byte 1 is X28-X2F and so on. Does that sound right? Should be 8 bytes total (64 inputs on that card). Do you know how you're telling it to read the inputs (X addresses) versus the outputs (Y addresses)? Edit: Just noticed you use the dwAddress in the request.abyAddress declaration. Doesn't really inform me any more though! That stuff is how you're reading the data, right? Edited 1 Jun 2016 by JRoss misread OP Share this post Link to post Share on other sites
Posted 6 Jun 2016 Thanks Jeremy. Got things working late last Friday. The default UDP port is 5000 but sometimes I have to use 5001 or 5002 (maybe other copies of GX Works are running on other computers). It turns out a lot of the values are essentially fixed; e.g. GX Works shows the network as Network 1 but I have to use Network 0. Module I/O and Module Station are similarly fixed. I'm still not sure what counts as a 'module' in PLC parlance, is it an individual unit plugged into a slot or is it a collection of units plugged into the backplane? I'm still working on adding to my driver but I can do DI, DO, AI, AO so the basics are covered. When I'm done I will publish my code somewhere in case it can help others. //read DI route.byNetwork = 0; route.byPC = 255; route.wDestinationModuleIO = 0x03FF;//0x03e1 can also work route.byDestinationModuleStation = 0; request.wDataLength = 12; request.wCPUTimer = 10; //0 = infinite wait; time = 250ms*x (4 = 1 second) request.wMainCommand = PC_BatchRead; //0x0401 request.wSubCommand = 0x01;//0 is word; 1 is bit dwAddress = 0x21;// head (starting) device number request.abyAddress[0] = reinterpret_cast<BYTE*>(&dwAddress)[0]; request.abyAddress[1] = reinterpret_cast<BYTE*>(&dwAddress)[1]; request.abyAddress[2] = reinterpret_cast<BYTE*>(&dwAddress)[2]; request.eDeviceType = PDT_X_Input; //0x9C request.wDevicePointCount = 0x1; by = byte, w = word/2 bytes, dw = double word/4bytes, e = enumeration/1 byte. The reason I have the address like this is because there are no 3 byte numbers in C++. Intel PC and PLC are little endian so the least significant byte goes first //return message from PL; in this case the data length will be 1 so there will be 1 additional byte that shows the digital state. It seems like the PLC can show 2 bits per byte so 0x10 would be first bit on, second bit off (or unused), 0x11 would be first and second bits on. struct SResponse { WORD wResponseDataLength; WORD wCompleteCode; }; Share this post Link to post Share on other sites
Posted 6 Jun 2016 Excellent! Module is the term for an individual unit that attaches to the PLC to provide I/O, communications, etc. In your case, that means the pieces that plug into the backplane. (e.g. a QX42 is a digital input module) Some PLCs don't have a fixed backplane, but are joined together using connectors or ribbon cables between the modules. Share this post Link to post Share on other sites