Sign in to follow this  
Followers 0
andyhill

Software Multiplex'd Code

9 posts in this topic

What I am trying to do is reuse one Task muiltiple times (up to 32 times) so as to use less memory and save having 32 identical tasks. How I have done this so fas is that I copy the data in from the controller task(using a CPS copy) into the local task , process it and then return it to the controller Database using a CPS copy. - That works unless... The problem I am having is that the HMI has to write to the Controller db for e.eg task12 (originally it used to write directly to the task eg task12) to make valve movements, however the CPU copy from the Local to the Controller is overwriting the command sitting in the controller DB before it can be passed to the mulitplex for processing (all to do with timing). Any suggestions on how to resolve this. All data is in arrays of UDT's with Command and Status's in the same nested structure. We also have the PLC clear the command bit to show that the command has been actioned OOOO my head hurts thinking about this today Edited by andyhill

Share this post


Link to post
Share on other sites
Are you using indirect addressing? It seems to me that maybe you're going about your addressing structure wrong. You need separate tags for each of the 32 tasks, but only one ladder routine that all of your tags will get fed through. Indirect addressing uses the JSR (jump to subroutine). You put your data into the JSR and use that to jump to your subroutine that you'll use for the 32 tasks. I don't have my thumb drive on me today. I'll bring it in tomorrow and I can explain in a bit more detail. It has a couple examples. Also, what platform are you on? RS5000, 500? Seimens? I really only know Rockwell, and my answer will reflect that. Edited by IamJon

Share this post


Link to post
Share on other sites
Here's an archived thread about IA: http://forums.mrplc.com/index.php?showtopi...aded&start= If it shows up with only 1 post, on the top right click 'options' and select 'standard' under 'display mode' OR: Why not just create a new array for the data that is going to the HMI for all 32. Then, when the routine is complete, move that data to the HMI tags. You can set a register or counter that will keep track of which of the 32 tasks you're on and copy the data into the appropriate HMI tags based on what the value in the register/counter is. Edited by IamJon

Share this post


Link to post
Share on other sites
Hi Andy, I usually do something similar to this, but I just use separate programs inside the main task instead. I'll just assume that you have a good reason that you're doing it the way you are. That aside, this problem is something that I have struggled with as well. This is the solution I have come up with, but I don't know if it is the best one, or if it will work with what you have... What I do is assign each logical object a unique identifier (similar to a database), and use that as a reference when looking up the IO for that object. That way, whenever I want the current status of a given object's IO, I just pass that object's unique id to a subroutine designed for that specific input or output which returns it's current value. I might not be explaining it the best, so here is an example: I want to update the bin selection bit for all of my bins in the sourceBins array before I make some decisions: FOR x := 0 TO SIZE_SOURCE_BINS - 1 DO JSR(lookupBinSelection, 1, sourceBins[x].binId, sourceBins[x].isSelected); END_FOR; //do stuff... lookupBinSelection(dint someBinId): SBR(someBinId); CASE someBinId OF //---------------------------------- // Bin #01 //---------------------------------- 01 : binSelected := bin01_selection_input; //---------------------------------- // Bin #02 //---------------------------------- 02 : binSelected := bin02_selection_input; //Add more bins here... ELSE binSelected := 0; //Log the error for troubleshooting JSR(loggerBinId, 2, someBinId, STRING_SELECTION); END_CASE; RET(binSelected); All of the inputs and outputs are updated every scan by the mapIO routine: //---------------------------------- // Bin 501 //---------------------------------- //bin01_selection_input := ABMill_N59[10].01; bin01_selection_input := test_bin01_selection_input; //bin01_speed_input := ABMill_N59[00]; bin01_speed_input := test_bin01_speed_input; //---------------------------------- // Bin 502 //---------------------------------- //bin02_selection_input := ABMill_N59[10].02; bin02_selection_input := test_bin02_selection_input; //bin02_speed_input := ABMill_N59[00]; bin02_speed_input := test_bin02_speed_input; //etc... You can change things up a little to write values instead of read them as well. If some of the "plc elders" have a better way of doing it, or have comments about my solution, please post them. I am always ready to learn different ways of doing things. Hopefully that will be of some help to you. --HandledException

Share this post


Link to post
Share on other sites
Here goes a headache: Step 1 : Let's assume you have a set of tags called Task1_NNN where NNN identifies some unique attribute. You also have Task2_NNN, Task3_NNN and so forth to Task32_NNN. These tags {Task1_NNN ... Task32_NNN} comprise your controller database so to speak. Step 2: Now for any given task you CPS copy TaskY_NNN to a tag TaskMaster_NNN ; jump to a subroutine which processes the TaskMaster Tags and then : CPS TaskMaster_NNN to TaskY_NNN. YOur value of Y can be anything 1 thru 32. Step 3: Now lets look at the case of Task1_CycleStartRequest and Task1_CycleRunning tags. Your subroutine looks at TaskMaster_CycleStartRequest if it is on it turns on TaskMaster_CycleRunning and then turns off TaskMaster_CycleStartRequest. Now if you are processing Task1 when the HMI turns on Task1_CycleStartRequest then the CPS at the end of processing erases the HMI request. Step 4: What you need is a set of tags for HMITask1 thru HMITask32 and allow the HMI to inteact with these not the controller DB. You then CPS between the Task1_NNN and HMITask1_NNN tags based on whether it is input or output information at a known time in the scan sequence. Step 5 : If you understand Step 4 above you can also streamline things by using an TaskHMI_NNN set of tags and an HMITaskNumber tag and bot ahve to create 32 sets of HMI tags. This whole problem occurs because HMI Updates are Asynchronus to the scan and program execution.

Share this post


Link to post
Share on other sites
OK what scares me most about everyones answers so far is that you are all employing JSR with parameters. When an addon instrcution can be used to do the same as a JSR with parameters. Advantage of the addon is that it has it own memory space/ security/ Stack etc......... Currently we are doing something simalar using dymanically addressed addon instructions....

Share this post


Link to post
Share on other sites
That's a pretty flippant response for someone asking us to help him with his problems. If you already had the idea of using add ons to solve your problem, why didn't you mention that? There are a number of unknowns when trying to help someone with their problems via the forums: architecture, design requirements, and technical ability/knowledge to just name a few. We are not mind readers. With that said, I would advise against putting your entire program (or a large portion thereof) into an add on. In my opinion that's not what they are designed for. I personally use add ons to encapsulate small bits of logic which I use often, which helps me out a lot in the code re-use department. Other than that I chop things up logically into programs and go from there. In the end add ons are just another tool in our arsenal, complete with their own strengths and weaknesses. It sounds to me like you have already made up your mind about what you are going to do, but just wanted to check the forums to see how your solution compared to ours. That isn't a problem in and of itself, but when you don't agree with the solutions provided I think you should handle it a bit differently next time. Last but not least, if you intend to put add ons in the controller scope and call them from multiple tasks just be sure that your add on is thread-safe, otherwise you will run into concurrency issues which are pretty tough to troubleshoot. Good luck with your project. --HandledException

Share this post


Link to post
Share on other sites
Actually, add-ons were intended for what you suggest but I've noticed that even some of the AB guys are now suggesting that addons accidentally became a way to implement true modular programming with data encapsulation, hiding, etc. These conceptual ideas have been floating around in the traditional programming world for years and have slowly shown to be valuable over the past couple decades because it allows for separation of concerns. In other words, I can program a "black box". The black box takes some input data, does something useful, and outputs some other data. Once the box is written, I can use/reuse the box as often as desired or needed while working in a different part of my program. Inside the black box, I can forget about the details outside the box and deal only with what the box is intended to do. Using this style of programming, code tends to be a few lines long at most and it simplifies things down to the point of reducing bugs and errors substantially. Until the add-on instruction came along, PLC's really didn't have a good way of doing this. It's not true object-oriented programming because the AOI's are not encapsulated inside the data structures (UDT's) and because the UDT's are global in scope. But, it's getting closer and gives you roughly 90% of the object-oriented programming result. The larger problem I have with it is dealing with the environment. It's the same argument that argues for the use of ladder logic and/or function block rather than structured text...that is, one of your target audiences (electricians) would be utterly confused by that style of programming and have a very hard time troubleshooting a modular program implemented with nests of add on instructions. SOOO....we have routines, programs, and tasks. It's not quite as fancy and creative as the AOI but with some proper care and feeding, you can get close to the same goal. To date, I've toyed with the concept but since I can't get over the hurdle of what to do about maintenance folks, I haven't used AOI's as a true programming idiom yet.

Share this post


Link to post
Share on other sites
Coming from an computer science background I can totally agree with you on the benefits of encapsulation, separation of concerns, etc, but I just think that the Logix5000 platform can't pull it off well enough to merit a complete paradigm shift into add-ons. Entering into the automation field with my OO background I have tried pretty hard to model the traditional OO paradigm in my PLC programs, but I always seem to run into platform architecture/implementation problems which call for ugly hacks that nullify most, if not all perceived gains in the process. That's why I tend to go with a happy medium of tasks, programs, routines, and add-ons. My two cents, HandledException

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
Sign in to follow this  
Followers 0