STEP7 UDTs and initial values.

I worked with ProTool only a few times, and it leaves a lot to be desired

It's not brilliant, but apart from the problem with the symbol updates, it would be perfectly adequate. Unfortunately, I'm going to be pushed onto WinCC, because the customer is insisting on it. I was involved with a project using WinCC a couple of years back and I can't say I was very impressed. It was anything but intuitive and for some operations you had to use two wizards one after the other, which I found a bit daft.

I hope it's improved in the meantime, there's a copy of WinnCC flexible 2004 advanced sitting looking at me on my desk, but after some of the comments I've read here, I'm not sure how much of a hurry I ought to be in to install it!

I look forward to seeing your sample project later - it sounds like the answer to a ******* prayers, well mine anyway!

Cheers

Roy
 
S7Guy: Could you explain this further?

Not quite. Functionally, it would look the same, but when you assign a UDT as an FC Input/Output variable, the scan time increases considerably, because the operating system spends a bunch of time passing each individual item into the function. But because the UDT in an FB is assigned to the STAT, it doesn't have to pass anything in. As a result, it runs as fast as though you were directly addressing the variables.

I'm not sure what you mean with the "But because the UDT in an FB is assigned to the STAT, it doesn't have to pass anything in."??
If you assign anything to the stat part of the FB then you have to create a instance db for this (at least as far as I know).

Regards
Borte
 
Hello guys;
Here is an excerpt from the pdf document "Programming with Step 7" that might shed some light on this subject:

Hope this helps,
Daniel Chartier

multi-inst.jpg
 
Where the heck did you dig that up! I've downloaded everything I could find on the Siemens web-site, I hate to think how many MB, and I sure haven't fallen over that one!

Having said that, I've read it three times, and I'm still not sure that I understand it. There again, that's about par for some Siemens documentation. Or maybe it's just that the wine glass is nearly empty!

I think I better wait for S7Guy's sample project!
 
Last edited:
Ok guys, I whipped up a sample project on the flight home tonight, but I'll post it in the morning. It looks flawless under the influence of a bottle of Louis Martini Cabernet, but I want to double-check it once more. :)

I'm not sure what you mean with the "But because the UDT in an FB is assigned to the STAT, it doesn't have to pass anything in."??
If you assign anything to the stat part of the FB then you have to create a instance db for this (at least as far as I know).

No, there is one way around it, and it works pretty slick. I would explain it now, but it's better if you see the project first.

RMA, this may be beyond your control, but you may want to discuss the WinCC decision with your customer. Personally, I would use VB and an OPCServer. It would be much cheaper, much more flexible, and easier to implement (plus, VB programmers are everywhere). WinCC had it's place a few years ago, but I can't see any big advantage of it any longer. Once in a while I'll bring my version up, but I can barely get through the wizards before I say "to hell with it". I think anyone could teach themselves VB quicker.
 
RMA, this may be beyond your control, but you may want to discuss the WinCC decision with your customer.

Unfortunately, it is beyond my control. The customer already has WinCC in house and is insisting for compatability reasons. The most I can do is to hold off implementation till the end of the project in December 2005 - which I may do depending on what I hear about WinCC flexible over the next few days and weeks.

Cheers

Roy
 
Hello guys;
Here is an excerpt from the pdf document "Programming with Step 7" that might shed some light on this subject:

In the cool morning light everything looks clearer! This is just the normal multiple instance declaration, although I didn't recognise it as such, because in the excerpt quoted there is no mention of the DB you need for the first FB.

I've been assuming that when S7Guy says no DBs, he means just that, not just multiple instances - I guess we'll find out when he posts his sample project.

Thanks nonetheless though Daniel, I must admit I've not used multiple instances very much recently and as a result tend to forget that they exist!

Cheers

Roy
 
I've been assuming that when S7Guy says no DBs, he means just that, not just multiple instances

No, I didn't mean no DBs at all. That would be impossible. What I mean is that I can use FBs without a declared IDB, and use a shared DB instead. I think Daniel's example sort of does the same thing, but I prefer my method because I don't have to enter any variables at all in the FB except for the UDT that AR2 is mapped to. It just seems cleaner to me.


Anyway, here it is. First, a few notes:

1. Obviously, if you have a small machine with just a few IO with a program that will be rarely updated, it won't be worth it to use this method. But, I have used it successfully on medium to very large projects (up to 100 nodes), and it has sped up development dramatically because I could add elements in my DBs without changing any code whatsoever.
2. Except for a function that is called on startup, I don't need to assign any parameters in block calls. There isn't anything wrong with input parameters I guess, but I found it a big pain to have to update the calls if I had to add a new parameter. This method eliminates that problem altogether.
3. One goal of mine was to create a programming environment where maintenance is practically nil. If someone else makes a program change, I don't want to have to worry about whether pointers or absolute addresses are being affected somewhere. Or, if someone adds another station (or whatever your machine components are called), it shouldn't be necessary to edit (or add) a bunch of blocks. Rather, I can just create the FB and drop it in my Station Calls "container". And, since almost all of my FBs use the same STAT variable (one udt) with no other input variable, if I need a new FB, I just copy an old one and edit the code.
4. The code approach, regardless of the complexity of the machine or number of IO, looks like this: On start up, the DB is analyzed and pointers are calculated. It just works, and there is nothing to troubleshoot here. In OB1, each station is called, and AR2 is indexed based on the previously calculated pointers. Within each Station call, I first map the real-world inputs, then execute the control code, and then map the results to the real-world outputs.
5. You can see that there is nothing in the core code that cares if someone decides to change the IO addresses. Rather than changing it in dozens of places, you only have to change it in the Machine Config function (or at a Config GUI, your choice).
6. You will see that I only use one shared DB. Actually, you can easily use more than one, but I've found it easier to use one as long as it doesn't get too big (I have some with over 50,000 bytes). I realize this goes against the Siemens concept since they allow you to have thousands of DBs and offer the instance DB functionality, but why bother switching blocks if you don't have to?
7. At first, this code won't make any sense at all. But after a while, it becomes so easy that you can't believe you ever did it any other way. So, before you discard it, give it a shot. It just might pay off, depending on your projects.
8. If you want to create your own project, the only requirement is that you select symbolic address priority. Also, if you change any UDT structure, recompile the code by going to Blocks>CheckBlockConsistency>CompileAllBlocks, and you'll be all set.
9. Don't be alarmed by my use of STL. Except for the start-up block, you can program your regular way. I'm just more comfortable with STL. Also, although I haven't tested it yet, I think this code will run. I substituted "MW" for IW,QW,PQW in this project, and it should map to those bits just fine.
10. Finally, this approach makes it a cinch to maintain a GUI interface. The shared DB can be exported as a text file, and you can do whatever you want with it from there. So, if the absolute addresses change after a UDT structure change, you can automate the GUI tags changes very easily. If you were using dozens of IDBs for this, it would be a nightmare.

Ok, enough rambling. Have fun.
 
S7Guy!

Thanks for posting the sample project.

I still haven't understood the logic but I just have a quick comment (i'll keep trying to get a grasp of the rest)...

The code of FC10 is this:

Code:
      UC    "FB Load Inputs"
      UC    "FB Setpoint Evaluation"
      UC    "FB Drive Logic"
      UC    "FB Machine Logic"
      UC    "FB Load Inputs"

Shouldn't the code rather be:

Code:
      UC    "FB Load Inputs"
      UC    "FB Setpoint Evaluation"
      UC    "FB Drive Logic"
      UC    "FB Machine Logic"
      UC    "FB Transfer Outputs"

I just changed the last line to call FB21 instead of another call to FB20.

I assumed that you read your inputs, change the status then transfer your outputs.

This may not me correct but I just wanted to confirm my thinking.

Regards
Borte
 
Darn it, isn't that the way it goes. I scour it making sure I didn't make a stupid mistake on the hard parts, and I miss the obvious. Thanks for the catch.
 
No, I didn't mean no DBs at all.

Oops, my dyslexic fingers again! I meant IDBs of course! I hadn't realised you could call FBs without their IDB by using UC or CC - that alone is a major milestone.

Have so far only had time to have a quick look at the sample program and I'm going to have to go back and reread it a few times before I begin to understand it (never mind fully!). Thanks very much for posting it, if I can bend my mind around it, it looks like being very useful!

Cheers

Roy
 
S7Guy,
I have briefly skimmed your code. It looks very impressive, and you have done an excellent job in commenting your code. Of course, making 'generic' code means that you can comment it well (because you save time), but also that you must comment it well (because it adds a layer of abstraction).

I am not sure that I can use your system though.
I have the following reservations:

1. It looks like you specify the first address of the inputs and outputs respectively.
"DB Stations".Station[1].Configuration.InputCardAddress
From that I follow that your i/o must follow a particular sequence, and that the other i/o is indirectly specified by the first i/o.
This means that if you want to add some i/o, you are locked by the standard sequence.

2. I am afraid that your system will make it difficult to make alterations to the code when online.
If I make a change to a UDT it would require me to restart the project (I believe the pointers will have to be recalculated if an UDT is changed).
Thats impossible on a running system.

Apart from that I think that your code looks very elegant, and I havent ruled it out completely.
 
From that I follow that your i/o must follow a particular sequence, and that the other i/o is indirectly specified by the first i/o.
This means that if you want to add some i/o, you are locked by the standard sequence.

No, you can assign any IO addresses you want. For instance, whatever value is in the "InputCardAddress" is what will be used for executing that station, so there is no requirement to follow a certain sequence (I could have used any values in the Machine Config FC). Also, I didn't mention it in the sample because I didn't want to complicate things, but you could also include a card type (8pt, 16pt, 32pt), so you would know which addressing to use (I know the hardware guys like to slip in a smaller card sometimes so they can save a couple of bucks :) ). Typically, I'll let the hardware guys define the IO nodes and addresses to whatever they want (it's easier if they do it since they are the ones doing the drawings and documentation), and I just do the config when they are finished. I give them no limitations whatsoever as to what the addresses should be (as long as they don't break Siemens rules).

Also, there is nothing stopping you from assigning the same input card to two or more stations. Let's say the hardware guys like to standardize on 32pt cards so they can make their remote boxes generic (I can't blame them). And let's say that Station 1 uses 27 inputs, Station 2 uses 9 inputs, and Station 3 only 5 inputs. Station 1 would get it's own IO, but the next two stations will share. You would simply enter the same address for Stations 2 and 3, and your code wouldn't know the difference as it looped around.

Lastly, there will always be some stray devices that are just randomly hung out on the machine somewhere (maybe a remote stop, a start/stop station, who knows), and is hooked up to any available IO points. In this case, I enter the addresses at the bit level (through the same config screen as the input cards), so even the special IO ends up being generic.

I am afraid that your system will make it difficult to make alterations to the code when online.
If I make a change to a UDT it would require me to restart the project (I believe the pointers will have to be recalculated if an UDT is changed).

Yes, if the length of a UDT is changed, then you have to download a new project so the pointers are recalculated, but that is actually the only limitation I face, and since there are no called parameters in the FBs, it is otherwise simple to make online changes. Previously (and I'm going all the way back to the S5 dark ages), there were all kinds of things that were not permissible on a live system. For instance, it could be tricky to add new parameters to the called block and calling block at the same time and download them without crashing (in this method, every bit in the UDT is avaiable as an Input/Output parameter). Or, if I wanted to insert a dozen new variables in the middle of the DB, I would have to either make sure I reserved some "spacer" memory in the DB to allow for this, or go through all of my code and adjust any absolute values that might have been affected. Looking at the whole picture, from my experience I have been inconvenienced less with this method I think. Of course, a lot depends on the development environment. If you are working in a steel mill where stopping the PLC could be catastrophic, the that definintely has to be considered.

For the times during development when I know I will need to add new variables to my FB logic and I don't know ahead of time what they will be, I'll include some test variables of different variable types in my UDTs, such as "TestBool_1", TestBool_2", TestDint_1", etc. Then, I'll use them in my new code "on the fly", and rename them whenever it's convenient. That seems to work pretty well, and it cuts down on new compiles significantly.
 
Also, there is nothing stopping you from assigning the same input card to two or more stations. .. And let's say that Station 1 uses 27 inputs, Station 2 uses 9 inputs, and Station 3 only 5 inputs. Station 1 would get it's own IO, but the next two stations will share. You would simply enter the same address for Stations 2 and 3, and your code wouldn't know the difference as it looped around.
I really dont understand this, in particular the underlined part.
I thought that in your sample project you only specified a start address, and the other addresses were somehow derived from that.
What I was worried about is if I had physically allocated some i/o like this:

I0.0 (station 1)
I0.1 (station 1)
I0.2 (station 1)
I0.3 (station 1)
I0.4 (station 2)
I0.5 (station 2)
I0.6 (station 2)
I0.7 (station 2)
I1.0 (station 3)
I1.1 (station 3)
I1.2 (station 3)
I1.3 (station 3)
I1.4 (not used)
I1.5 (not used)
I1.6 (not used)
I1.7 (not used)

and then I had to add an input to station 1 because some condition in the project had changed in the meantime. Only from I1.4 would there be some free addresses, but if I had to follow a predefined sequence, then I had to move all the other inputs in order to squeze the new input for station 1 in at I0.5.
 
S7Guy

Without going in to any of the application-related nature of your code, could I just offer many thanks indeed for the time and effort you spent on producing this excellent example. I think it has opened quite a few people's eyes to alternatives to the 'conventional' methods of program design and structure.

Somewhere at the back of my mind I think I knew that AR2 and FBs were linked somehow, but I've never seen it displayed or used so audaciously as this! You've not just used it as a little tweak - this is the whole underpinning of your code.

Whether anyone finds their applications lend themselves to adopting this exact approach is, I think, irrelevant. At least we all know now that there is yet another route available. And at some point in the future, just when we think all the options are closing off around us on a particular problem, I bet someone will remember "Hey, what was that thing S7Guy did with AR2 and the DBs?"

Thanks again.

Ken
 

Similar Topics

This is the first time I am working with Simatic Manager Step7 as I started my siemens journey with TIA which is pretty easy and do a lot of stuff...
Replies
2
Views
59
When you download a DB, the values get overwritten by what is in the "actual" column in offline DB. Does this happen at the start of the PLC...
Replies
6
Views
137
Hello Inside a FB, I´m trying to transfer a string from a DB to a IN_OUT var that was define as a UDT. The problem is that i can´t determine the...
Replies
4
Views
121
Hi all, I am trying to convert RSLogix 5000 program to Step7. I need to bit shift left my array of double integers for tracking the product on...
Replies
2
Views
515
I have a word in some DB which I want to load to AR1 and use as a pointer. In order to do this I need to write L DBxy.DBW xy SLD 3 LAR1 I...
Replies
3
Views
526
Back
Top Bottom