Rocinante8

communication with PC

8 posts in this topic

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

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


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

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

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

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 by JRoss
misread OP

Share this post


Link to post
Share on other sites

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now