[Logix] Trying to understand MSG vs Produce/Consume communications

defcon.klaxon said:
I am assuming you are naming your subroutine PACK_Data and UNPACK_Data and that those aren't functions native to Logix, right? As in, I need to create those rather than grabbing them as a Functional Block.
I can't speak directly on Ken's behalf obviously - but I believe you're right. I do the same thing (although my wording is slightly different) - I have a routine where all the data that's going to other controllers is mapped into a data structure that's easy to transmit, and one routine where all the data being gotten from other sources is mapped from tag arrays back into the relevant places in the code. Whether I'm using MSG instructions or produced/consumed tags, I always "pack" and "unpack" the data the same way, so that it's easy to work out where the data is originating from or going to.
 
I can't speak directly on Ken's behalf obviously - but I believe you're right. I do the same thing (although my wording is slightly different) - I have a routine where all the data that's going to other controllers is mapped into a data structure that's easy to transmit, and one routine where all the data being gotten from other sources is mapped from tag arrays back into the relevant places in the code. Whether I'm using MSG instructions or produced/consumed tags, I always "pack" and "unpack" the data the same way, so that it's easy to work out where the data is originating from or going to.

I've been doing some reading and this sounds like the way many are doing it when data flow control is important, thanks for commenting on how you do it. I may have some questions on how to properly implement this in Logix, if you wouldn't mind a few questions via PM.
 
I've been working with packing data into DINT arrays; it seems to work well that if you create an array of DINTs you can pack in boolean values, and then integer values. But what if I need to send REAL values? If I don't convert anything and program a MOV from a DINT to a REAL, it automatically adds a decimal point (and I assume it interprets the bits as a REAL instead of a DINT). Should I just create DINT packages for BOOLs and DINTs and REAL packages for REALs? I'm going to keep experimenting but if anyone has a suggestion I'd love to hear the best way to do this; I'm seeing a LOT of work ahead in getting these data packages together and if I'm doing this the hard way I'd love to hear some points on how to do it more efficiently (since I have multiple remote sites and it seems like each connection will have to be manually configured for PACKing and UNPACKing).

Thanks!
 
Last edited:
Should I just create DINT packages for BOOLs and DINTs and REAL packages for REALs?

Yes, that's exactly how I do it.

You could create a User-Defined datatype that includes BOOLs and DINTs and REALs, but to message those between controller (or use Produced/Consumed) you must have identical UDT definitions on both sides, which is another detail to keep track of.

When you just use a DINT array and another REAL array, all you have to keep track of is the size of the array.
 
Yes, that's exactly how I do it.

You could create a User-Defined datatype that includes BOOLs and DINTs and REALs, but to message those between controller (or use Produced/Consumed) you must have identical UDT definitions on both sides, which is another detail to keep track of.

When you just use a DINT array and another REAL array, all you have to keep track of is the size of the array.

Awesome, thanks so much Ken!
 
So this is going to be a strange addition but do you (defcon.klaxon) think it would be possible for you to send me a message telling me what you think of the Xetawave devices (when you get a chance to work with them)? I’ll send you a private message so I’m not taking up space here but I wanted to make sure you saw this (I always forget to check my messages).
 
Ken is spot on there. If you have the ability to control both ends of the data transfer, a UDT can be very handy. In one particular factory where I'm lucky enough to have a proper say in all the PLC-related decisions, all the machines share data using a UDT called COMMS. This is just one DINT called BitData (so I have 32 discrete bits for each transfer) and an array of 20 REAL's. It also has a Status bit for automatically monitoring the connection status without the need for a heartbeat, although this only works if you're using produced/consumed tags. Being able to do that makes the comms setup very straightforward.

defcon.klaxon said:
If I don't convert anything and program a MOV from a DINT to a REAL, it automatically adds a decimal point (and I assume it interprets the bits as a REAL instead of a DINT).
Yes, that's correct - a MOV instruction is actually quite a complicated instruction internally as it takes whatever value you give it, in whatever format you like, and converts it to the destination format. As opposed to say a COP instruction which just copies the literal bit pattern and will give you gibberish if you use different data types.

As for how to do it more efficiently - if your data structure is the same, and needs to be unpacked the same way in all PLC's you could potentially use an AOI. At the aformentioned site, each machine sends data to a central line controller via produced/consumed tags, in a UDT. I then copy that UDT directly into an AOI called "MACHINE", which splits out all the information and maps it into meaningful tags. So I'll map CommsIn_Oven to my Oven AOI, and then the AOI splits out all the data into Oven.Running, Oven.AtTemp, Oven.Speed, Oven.Temperature, and so on. It means that you have to do a lot of forward planning and work out some kind of universal data structure that has space for any and all parameters any system can use, but if you've got similar things happening across the board it's quite doable.
 
Ken is spot on there. If you have the ability to control both ends of the data transfer, a UDT can be very handy. In one particular factory where I'm lucky enough to have a proper say in all the PLC-related decisions, all the machines share data using a UDT called COMMS. This is just one DINT called BitData (so I have 32 discrete bits for each transfer) and an array of 20 REAL's. It also has a Status bit for automatically monitoring the connection status without the need for a heartbeat, although this only works if you're using produced/consumed tags. Being able to do that makes the comms setup very straightforward.

I've gotten things working here with packing into DINT and REAL arrays, but will definitely take a look at UDTs and how to set them up.


...As opposed to say a COP instruction which just copies the literal bit pattern and will give you gibberish if you use different data types.

Thanks for the explanation of the difference. I will keep the COP instruction in my back pocket in case I ever need to use it.

As for how to do it more efficiently - if your data structure is the same, and needs to be unpacked the same way in all PLC's you could potentially use an AOI. At the aformentioned site, each machine sends data to a central line controller via produced/consumed tags, in a UDT. I then copy that UDT directly into an AOI called "MACHINE", which splits out all the information and maps it into meaningful tags. So I'll map CommsIn_Oven to my Oven AOI, and then the AOI splits out all the data into Oven.Running, Oven.AtTemp, Oven.Speed, Oven.Temperature, and so on. It means that you have to do a lot of forward planning and work out some kind of universal data structure that has space for any and all parameters any system can use, but if you've got similar things happening across the board it's quite doable.

There are always compromises to be made; time invested now for easier programming later, versus how helpful that invested time will be. At this point I think I'll shy away from the "universal" solution as I'm already quite deep in learning AB 5000 programming already; but, the idea of making universal structures is a good one and perhaps when I have more time to iron things out I'll incorporate something like that. Thanks!
 
OK, so I've gotten things working with packing and unpacking data, and have it controlled so I can do discrete polling.

The last thing I want to make sure I understand is the JSR instructions, and how the programs and routines respond. Right now everything is working as intended but it's a very simple proof of concept, and in the actual programming for the project things will be more complex.

First off, I'm not passing any parameters when I'm calling subroutines; should I be? I mean I know it's optional, what I'm actually asking is there some sort of error checking or keep-from-locking-up-in-an-infinite-loop sort of reason to add a parameter and pass it from main program to subroutine?

Secondly, if I'm not passing parameters then it doesn't seem like I need any SBR or RET instructions; is that true?

Third, how does Logix5000 actually respond to the JSR instruction? What I mean is, in my MainProgram I jump to a subroutine and it seems to come back to the MainProgram automatically; does it run the subroutine logic once and then come back to the MainProgram where it left off? Do I need an END instruction at the end of a subroutine? Is there any reason why I'd want to be able to jump to a subroutine and stay there, or is that just asking for system hangups? Should I be controlling how often I jump to subroutines to keep the system from being overtaxed?

Thanks for all the help guys!
 
Last edited:
Correct, you do not need SBR or RET if you are not returning parameters.

FYI, most people do not use JSR the same way PC programmers use subroutines. In the AB PLC world most people use subroutine only a as a organizational method.

In the contrologix world, people use Add-On-Instruction for *real* subroutine type work.
 
All good questions! The main way that I use subroutines is very simple: break my logic up into different routines for ease of navigation and troubleshooting. Then, in the main routine, call each and every subroutine in order. The main routine does nothing else but call all of the other routines.

That's not to say its the only way of using JSR and subroutines - and in fact I have used them in several other ways as the application demands - but this is probably the simplest way to do things and if you're still "cutting your teeth", probably the best approach to make your own life easy while you work things out.

defcon.klaxon said:
First off, I'm not passing any parameters when I'm calling subroutines; should I be? I mean I know it's optional, what I'm actually asking is there some sort of error checking or keep-from-locking-up-in-an-infinite-loop sort of reason to add a parameter and pass it from main program to subroutine?

You don't need to pass parameters - if you're using the JSR's as I described above, all the instruction has to do is say "run that routine", "now run that routine", etc etc. An example of where you WOULD pass a parameter might be: you have 100 bins which all have one of 20 different products in it. Your program needs to find product 7. So, you write a subroutine that, given a product number, returns the first bin that (a) has product 7 in it, and (b) is not empty. Then, at the point your PLC needs to know where that product is, you use a JSR to call that subroutine, and pass the value "7" to the input. The subroutine finds product 7 in bin 56, so it returns a value of 56, and your code carries and perhaps sends a robot down to get bin 56.

defcon.klaxon said:
Secondly, if I'm not passing parameters then it doesn't seem like I need any SBR or RET instructions; is that true?
Correct. You only need to use those if you are handling parameters; otherwise the subroutine will get to the end and return automatically.

defcon.klaxon said:
Third, how does Logix5000 actually respond to the JSR instruction? What I mean is, in my MainProgram I jump to a subroutine and it seems to come back to the MainProgram automatically; does it run the subroutine logic once and then come back to the MainProgram where it left off?
Yes. If the PLC encounters a JSR instruction, it goes and executes that subroutine all the way to the end, then returns to the JSR instruction that called it, and carries on with the next instruction in the rung/next rung in the routine.

defcon.klaxon said:
Do I need an END instruction at the end of a subroutine?
Not explicitly. You'll note that Logix automatically puts in "end" rung at the end of each subroutine, and you can't delete that. You don't need a separate end instruction. There are occasions where you might want to stop executing a subroutine early and return back to the JSR, but they are reasonably rare and again, I'd recommend not delving too far into that sort of thing upfront as it can make things confusing, and usually for no good reason :)

defcon.klaxon said:
Is there any reason why I'd want to be able to jump to a subroutine and stay there, or is that just asking for system hangups? Should I be controlling how often I jump to subroutines to keep the system from being overtaxed?

This is perhaps not quite the right question to be asking. The PLC doesn't just "stay" in a subroutine, unless you code in an infinite loop, in which case you'll get a major fault on the task watchdog and your PLC will stop. I think your best approach is as I mentioned first up - just call all subroutines sequentially and let the PLC run through everything continuously. You really shouldn't have issues of "overtaxing" your PLC by calling routines that aren't necessarily "needed" right now, not in this day and age with modern processors - and if you did, you'd have deeper issues than just the way you were calling your routines.

Hope that gives you some sort of useful information!
 
Hope that gives you some sort of useful information!

Very much so, thanks so much for taking the time to answer each of my questions individually and for laying out the information; I really, truly appreciate it!

At this point I'm feeling like I've got the basics down, thanks so much for all the help you've provided!
 

Similar Topics

I am trying to understand an Italian CompactLogix program. It is for a dough laminator . The block looks like ....., Linearization X1. -500...
Replies
22
Views
5,916
Hi all, I'm starting work on a system and the processor for said project is a Control Logix 1756-L82. When I open Logix, however, that CPU is...
Replies
9
Views
2,943
Does anyone have experience communicating with the MAGPOWR Cygus Tension Controller thru Ethernet. I have a Controllogix 1756-L73 PLC Version 30...
Replies
25
Views
4,069
Hey everyone, I have a Keyence LK-G5001P control module with 2 laser heads connected to it (the lasers are Keyence LK-H152). I have the control...
Replies
3
Views
2,176
Good Morning , I received a used 1756-L62 / A CPU , from a vendor that was using it for a trainer. I tried to download a program that is...
Replies
4
Views
1,476
Back
Top Bottom