S7Guy
Member
Thanks Ken, but it was no problem putting this together, and I’m always glad to share. I used to teach Siemens PLC programming, so it doesn’t take long to put something together. It even helps me out to explain it to myself sometimes, and I’m glad if someone can get something from it, even if they can’t apply the approach to an entire project.
Also, I finally had a chance to look at the sample project again, and I caught a couple of other errors (in a couple of the FBs, I pasted the UDT as an In_Out declaration instead of a STAT). So, I’ll post it again with the corrections and you can toss away the old one.
Jesper, I see where you are coming from now. In my example, to keep things simple to explain, I assumed some kind of rotary assembly machine where each station had different functions but similar IO. If I had a machine where the IO was scattered all over the place or was radically different at each station, I would have to do something different. Here are some ideas:
1. If the IO is completely different at each station, but each station at least has its own IO, then I would come up with individual UDTs to describe that IO. Then, I might have to build my DB differently. If I had plenty of space in the DB, I would still use arrays and make all of the IO UDTs available to each station along with a configuration variable that told each station which IO to use. Or, if that is too clunky, I would skip the arrays and manually list each station in the DB with its own IO UDT. That would be a one time effort, and I would still be able to continue using my approach. The only thing I might have to do is calculate the pointers and lengths for each individual station at start-up if it’s possible that the UDT lengths could be different.
2. If the IO isn’t contiguous, then I would use bit pointers (each IO point would have its own DINT pointer). One problem is that this way of indirect addressing- “A I[#StartButton]” -is inefficient. It is essentially two instructions, plus S7 doesn’t let you use STAT variables in the brackets, so I would have to pass each dint into local memory. If scan time is not an issue, or if I only had a few IO, I guess that would be ok, but if I had thousands of IO, I would be resigned to mapping the absolute bits one by one in a custom function. I would hate to do that, but at least the custom hard-coding would be limited to a couple of functions. Thinking about it, since I use symbolic priority, it wouldn’t be to bad to do it like that as long as I made sure my symbol table was current.
Unfortunately, no matter which approach you use, if you make a change to a DB, I can’t think of a way of downloading the DB without stopping the PLC first. It would be like overwriting an MS Word doc while saving the text in the old one.
Also, I finally had a chance to look at the sample project again, and I caught a couple of other errors (in a couple of the FBs, I pasted the UDT as an In_Out declaration instead of a STAT). So, I’ll post it again with the corrections and you can toss away the old one.
Jesper, I see where you are coming from now. In my example, to keep things simple to explain, I assumed some kind of rotary assembly machine where each station had different functions but similar IO. If I had a machine where the IO was scattered all over the place or was radically different at each station, I would have to do something different. Here are some ideas:
1. If the IO is completely different at each station, but each station at least has its own IO, then I would come up with individual UDTs to describe that IO. Then, I might have to build my DB differently. If I had plenty of space in the DB, I would still use arrays and make all of the IO UDTs available to each station along with a configuration variable that told each station which IO to use. Or, if that is too clunky, I would skip the arrays and manually list each station in the DB with its own IO UDT. That would be a one time effort, and I would still be able to continue using my approach. The only thing I might have to do is calculate the pointers and lengths for each individual station at start-up if it’s possible that the UDT lengths could be different.
2. If the IO isn’t contiguous, then I would use bit pointers (each IO point would have its own DINT pointer). One problem is that this way of indirect addressing- “A I[#StartButton]” -is inefficient. It is essentially two instructions, plus S7 doesn’t let you use STAT variables in the brackets, so I would have to pass each dint into local memory. If scan time is not an issue, or if I only had a few IO, I guess that would be ok, but if I had thousands of IO, I would be resigned to mapping the absolute bits one by one in a custom function. I would hate to do that, but at least the custom hard-coding would be limited to a couple of functions. Thinking about it, since I use symbolic priority, it wouldn’t be to bad to do it like that as long as I made sure my symbol table was current.
Unfortunately, no matter which approach you use, if you make a change to a DB, I can’t think of a way of downloading the DB without stopping the PLC first. It would be like overwriting an MS Word doc while saving the text in the old one.