Ideas needed for Siemens S7 program

tesalmin

Member
Join Date
Oct 2003
Posts
36
Hello friends,

I've been asked to make program to a system that makes laminated beams from boards. I need some help or good ideas for some part of the line.
In the line there is a part where the fingerjointed boards must get dry and they will be stacked into "cages" and when dried they will be destacked and layed into one pressfull of beams.

The cages are destacked by LIFO principle. Also all the boards of the beam doesn't fit into one cage (depends on the thickness of the board there can be 5-15 board in one cage).

The problem is that I have to figure out the right order to produce the boards so that after stacking and destacking the beam has correct boards in right places.

I will put a principle diagram after this.

kestopalkki periaate.jpg
 
Interestingly, I just completed a project similar to this, where I had large "cages" of product that was unloaded LIFO. I’m not sure if you have already decided on an approach and just need answers to specific questions, or if you are looking for general ideas on how to handle your application. If you are just looking for ideas, I can describe how I would approach it, and if you want to give this method a try, I can help further:

I found it extremely helpful to use arrays in my program. For instance, I created a UDT of all of the various properties that my product could consist of (in your case, perhaps length, width, beam ID, etc). Then, I created an array of this property UDT, using the maximum number of possible products per cage to determine the size of the array, and defined the total products as its own UDT. Then, I defined a cage UDT which consisted of the products in the cage as well as specific cage properties. By doing this, I had discrete entities that I could manage very easily, even though the size of the “components” was much larger than a doubleword. Plus, a tremendous amount of data is now well-organized and accessible to an HMI.

Below, I’ve thrown together a sample DB that consists of a structure like I just described (I used 4 products per cage for simplicity). And, by setting the Address Priority to Symbolic, I can even insert new properties later if I want to, and I won’t have any absolute addresses to change. If I want to address a certain property (i.e. check the ProductID of one of the boards against the laminate ID), all I have to do is type the actual name:

L System01.Cage[1].Board[3].ProductID
L ActiveLaminateID
==I
= OkToUnloadBoard

Or, if I want to generate a fault on an HMI when the door is open, then I can do this:

AN System01.Cage[2].CageStatus.DoorClosed
= Cage2DoorFault

Or, if I store the length of each component somewhere (in our example, a complete cage is 44 bytes long), then I could create a pointer and call SFC “Block Move” to copy all of the data from one cage to another. And like I said before, by using symbolic addressing, I could change the size of the cage UDT without the rest of my code being affected.


Address Name Type
0.0 System01.Cage[1].LaminatedBoardID INT
2.0 System01.Cage[1].DesiredDryingTime DINT
6.0 System01.Cage[1].CurrentDryingTime DINT
10.0 System01.Cage[1].CageStatus.InPosition BOOL
10.1 System01.Cage[1].CageStatus.DoorClosed BOOL
12.0 System01.Cage[1].Board[1].ProductID INT
14.0 System01.Cage[1].Board[1].Length INT
16.0 System01.Cage[1].Board[1].Width INT
18.0 System01.Cage[1].Board[1].SequenceNumber INT
20.0 System01.Cage[1].Board[2].ProductID INT
22.0 System01.Cage[1].Board[2].Length INT
24.0 System01.Cage[1].Board[2].Width INT
26.0 System01.Cage[1].Board[2].SequenceNumber INT
28.0 System01.Cage[1].Board[3].ProductID INT
30.0 System01.Cage[1].Board[3].Length INT
32.0 System01.Cage[1].Board[3].Width INT
34.0 System01.Cage[1].Board[3].SequenceNumber INT
36.0 System01.Cage[1].Board[4].ProductID INT
38.0 System01.Cage[1].Board[4].Length INT
40.0 System01.Cage[1].Board[4].Width INT
42.0 System01.Cage[1].Board[4].SequenceNumber INT
44.0 System01.Cage[2].LaminatedBoardID INT
46.0 System01.Cage[2].DesiredDryingTime DINT
50.0 System01.Cage[2].CurrentDryingTime DINT
54.0 System01.Cage[2].CageStatus.InPosition BOOL
54.1 System01.Cage[2].CageStatus.DoorClosed BOOL
56.0 System01.Cage[2].Board[1].ProductID INT
58.0 System01.Cage[2].Board[1].Length INT
60.0 System01.Cage[2].Board[1].Width INT
62.0 System01.Cage[2].Board[1].SequenceNumber INT
64.0 System01.Cage[2].Board[2].ProductID INT
66.0 System01.Cage[2].Board[2].Length INT
68.0 System01.Cage[2].Board[2].Width INT
70.0 System01.Cage[2].Board[2].SequenceNumber INT
72.0 System01.Cage[2].Board[3].ProductID INT
74.0 System01.Cage[2].Board[3].Length INT
76.0 System01.Cage[2].Board[3].Width INT
78.0 System01.Cage[2].Board[3].SequenceNumber INT
80.0 System01.Cage[2].Board[4].ProductID INT
82.0 System01.Cage[2].Board[4].Length INT
84.0 System01.Cage[2].Board[4].Width INT
86.0 System01.Cage[2].Board[4].SequenceNumber INT
 
S7Guy,

Thanks for a good idea. I havent used arrays in plc programming before so I have to do some studying about the subject to understand it better. It sounds that this could be the way I'll try to handle the loading and unloading of cages.

Still I have the problem for solving the correct order of producing the boards. Exaple in my previous post: Rearranging the DB10 contents to DB11 by dividing the values into stacks of 5-15 (9 in the example)and flipping each stack around. DB10 is the order of laying the boards to press and DB11 is the order of producing the boards so that after loading and unloading the cages the beam will look like DB10.

The thickness of the boards in one beam will be the same so there will be the same amount of boards in each cage.

I thought of making pointers from the lowest board for each cage and then make a loop with indirect addressing that will go through DB10 and read the values from DB10 and then move it to right place in DB11.
(Basically DB10.DBW16->DB10.DBW0....DB10.DBW0->DB11.DBW16 then DB10.DBW34->DB11.DBW18...DB10.DBW18->DB10.DBW34 and so on.

I'm also not very familiar with loop programming with plc so it's only a thought I have.

I have to try to make some program to test my idea or if someone has good ideas I will be happy to hear them allso.
 
Ok, let's see if I understand this:

You are producing boards to make a beam. In your example, the beam requires 30 boards. Because the boards are unloaded LIFO, you can't simply produce the boards in sequence (1 through 30). Instead, you have to calculate how many boards will fit in the cages, and produce them so that when they are unloaded, they will come out in the correct sequence. Do I have that right?
 
Ok, so in your example you have determined that nine boards fit in a cage, based on the thickness. Is there a separate recipe somewhere containing things like thickness and length, and you manufacture them from this recipe? Do you always unload the cages in a certain order, or is that a variable as well?

I don’t think you will have to rearrange the boards in the data blocks at all. As long as the boards are produced and loaded in the correct order, they will be unloaded in the correct order. It shouldn’t matter if a particular board is in DBW16 instead of DBW0. In fact, the same math that is used to store the boards in the correct order in the correct cage can be used to unload them again.
 
I will try to explain more.
The operator makes a receipe that contains values about all beams for 1 pressfull of beams.
- nr. of boards in beam 1
- width of boards in beam 1
- thickness of boards in beam 1
- length of boards in beam 1
....and the same values for max 10. beams.

The outest boards of a beam must be A-quality (1/6 of the total nr of boards) and in the middle is B-quality. So I will calculate the nr of A-quality and B-quality boards needed and then I will make a list of the boards in the beam.

Then from this list I need to figure out the right order of producing the boards.

Here is one more drawing (Here is 10 boards in one cage and there are 3 beams in one pressing cycle). I hope it shows what I'm trying to say.

kestopalkki example2.jpg
 
Last edited:
The code that determines the number of A boards and B boards is fairly straight forward. I tested this code last night on a simulator I have, and if you force the number of boards in the beam into MD20, then it returns the correct boards of each type (You can copy and paste this code into an FC to test it as long as you create the local variables):

NumberOFBoards = DINT
ABoards = DINT
BBoards = DINT

L MD 20
T #NumberOfBoards

L #NumberOfBoards
DTR
L 3.000000e+000
/R
RND+
T #ABoards
L L#2
MOD
A ==0
JC m001
L #ABoards
+ L#1
T #ABoards
m001: NOP 0

L #NumberOfBoards
L #ABoards
-D
T #BBoards


Once you find the ABoards and BBoards, then you have to create your own recipe in the PLC. If I was doing this, then I would start at the beginning of a data block and then start filling it in, board by board. You used two bytes per board; was there a reason for that? Were you going to identify a board with an integer, such as ABoards = 1, BBoards = 2? Anyway, since the number of ABoards is always an even number, you would divide by two to determine how many are inserted initially. There are a few ways to do it, but I think it would be easiest to create a LOOP, with the NumberOfBoards determining the number of cycles in the loop. Then, as you filled the DB, you would increment a pointer by two bytes. Also, inside the loop you would have to keep track of how many of each type have been transferred. It sounds tricky at first, but it would be a neat little piece of code by the time you are done (plus, you would really understand Loops by the time you were finished. :) )

You would have to do this for each beam in your production run. When you are finished, you would have a list of boards in sequential order, starting at DBW 0 through, say, DBW 30. And, this is where I must be missing something in the mechanics of this system, because since it is LIFO, I don't understand why you couldn't just produce the boards in reverse order, starting at DBW 30. If so, the cages would look like this, assuming five boards per cage:

Cage 1: DBW 30 (Board 16)
DBW 28 (Board 15)
DBW 26 (Board 14)
DBW 24 (Board 13)
DBW 22 (Board 12)

Cage 2: DBW 20 (Board 11)
DBW 18 (Board 10)
DBW 16 (Board 9)
DBW 14 (Board 8)
DBW 12 (Board 7)

Cage 3: DBW 10 (Board 6)
DBW 8 (Board 5)
DBW 6 (Board 4)
DBW 4 (Board 3)
DBW 2 (Board 2)

Cage 4: DBW 0 (Board 1)

So, when you start producing the beams, they would have to be unloaded in reverse order, right? First, you would unload Board 1, then jump to Cage 3 and unload Board 2 (since it was the last one loaded in that cage) and so forth. This way, all of the data is only in one place, and you won't need to move it to another DB. I would suggest that you add additional properties to your boards (whether you use arrays or not) and mark certain boards as the "Start Of Beam", "End Of Beam", etc. I'm sure these bits would be useful as you develop the code.

It sounds like a fun project. Keep us posted.
 
I must be missing something in the mechanics of this system, because since it is LIFO, I don't understand why you couldn't just produce the boards in reverse order, starting at DBW 30

You can see the principle of mechanics in the drawing in my first post. Boards to one cage are loaded/unloaded LIFO, but the whole cages are unloaded FIFO. That is the thing that makes it so tricky.
 
Ok, I've got the whole picture now. I can imagine a way to do it, and it shouldn't be very difficult. I'm going to work now and won't be able to look at it further today, but I'll put together some code tonight and post it.
 
Ok, I've attached some code for you to look at. I avoided the symbolic programming because I’m afraid that you might not be familiar with it, so I used absolute addressing with pointers instead. I tossed it in a PLC a few minutes ago and it seemed to do what it was supposed to do.

Here is the approach I took:

If you look in OB1, you will see that I populate DB20 with hard-coded test data. In reality, your recipe will provide this data (all we care about for this example is the number of boards in each beam). I didn’t bother checking a min/max for the number of boards per beam, so I’m sure the code would “break” if you input some wild number like “1,000,000”. You can change any of the constants to see the effect on the data.

In OB1, you will see that there are four functions (FC1-4). You will have to force M24.0 to call them (a new recipe only needs to be processed once). I clear M24.0 immediately, so you won’t have to reset it yourself.

The first function, FC1, clears the data from the previous recipe by calling SFC21 and transferring zeroes into the old data areas.

Next, I call FC2 and rip through each beam and calculate the number of A boards and B boards for each, and create a sequential list of all boards. If you open up DB20, you will see that the first 40 bytes contain the beam data, followed by the individual board data. So you can follow what is going on a little easier, I included a Board Quality field (using data type CHAR so you would see either an A or B), as well as the beam instance and sequence number for each board.

After the board list is made, I call FC3. This function grabs the board list and actually fills “virtual cages” in DB10. For our example, I provided for a max of 20 boards per cage and a total of 20 cages. When I filled the cages, all I did was grab each board in sequence and start inserting the boards in the highest position based on the “boards per cage” value. Although the code supports 20 boards per cage, I used 9 for the example (this is hard-coded in FC3, but you can change it easily; your recipe should ultimately hand down the boards/cage). By the time FC3 completes, you will have a list of cages that should mirror your live production.

Lastly, I call FC4. This function loops through all the cages and creates an actual production list of individual boards. It’s kind of hard to explain in writing, but what it does is grab the last board loaded into Cage 1 of our virtual cages, and copy it to the Production List (DB30). It then grabs the next board, and so forth. The result is a list of LIFO boards that are unloaded from FIFO cages. Again, I included the beam instance and the original sequence number in DB30, so you can observe exactly what is happening. If you produced the boards in the sequence listed in DB30, they would load and unload to make the correct beams.

I hope this helps. I didn’t use any real I/O, so you can just copy these blocks to any PLC and try out the code. I checked the execution time, and the whole thing takes about 2.5ms, but if you streamlined it, you could get it down to less than a millisecond easily. But since it’s a one-shot, it probably doesn’t matter. I’m sorry, but there aren’t many comments in there (I wrote the code after dinner tonight, and wanted to get it out to you), but if you step through it you should be able to figure it out.
 
Thank you VERY MUCH S7Guy beerchug

I looked your program and there are just the things I wanted to do, but I didn't know how to write to program.

I think I have now all I need so thanks one more time!
 

Similar Topics

Good morning. Our plant production processes and machines are currently a mix of SLC 5/03 racks controlling critical systems, and a mix of...
Replies
5
Views
2,407
Hi Good Friends! I need your ideas here please: As an Automation Engineer, what solutions do you think you can deploy for an Enterprise Risk...
Replies
0
Views
1,531
Any ideas on how to setup a system that will monitor freezer tempratures and boiler steam preasures remotely via the internet? Any ideas...
Replies
0
Views
2,091
This is the scenario. We have 3 fluids to mix. One fluid is under constant pressure and the other 2 are pumped out. We have flow meters on all...
Replies
9
Views
2,491
I was just wondering if anyone had any experience with a VEGAPULS C 22 Radar sensor. One of my customers got a cold call from one of there reps...
Replies
10
Views
2,791
Back
Top Bottom