Step 7 Indirect addressing for machine with multiple part types

bri@zf

Member
Join Date
Aug 2006
Location
Maine
Posts
7
I am trying to modify an assembly machine that is capable of making several part types. I am adding an lvdt and want to be able to store different max and min values depending on which part type is running. The max and min values can be changed on an operator panel so it is necessary to store the new max and min value automatically when changing part types. Also, the last used parameters for the part type that is being changed to must be recalled. I am not very familiar with indirect addressing but there is some existing programming on other equipment here that already does what I want to do. I would simply like to know how it works before attempting to copy it. I have attached an image(I think) of the programming that I mention. Can anyone help?
 
bri@zf said:
...I have attached an image(I think) of the programming that I mention. Can anyone help?

Nope...try again

help.gif
 
Sorry, I had not noticed the error message that I got because the file was too large. I had to save it in two pieces. There is more programming than what I show here but this may be enough for you to see what is going on... Thanks for the quick reply
 
I have a simple suggestion.

Don't use indirect addressing. I suggest that you have a working DB that as the min and max positions and other data particular to that part. This is the data block that you always use while running. For each part you make a part DB which is defined using the same UDT as the working DB. When ever you change the part you are making you copy blkmov SFC 20 the data from the appriopriate part DB to the working DB. If the working DB has any values changed then a blkmov SFC 20 must copy the changed data back to the appropriate part DB. Hopefully you will not have more parts than DBs.

This method is:
1. faster. direct addressing is faster than indirect addressing. You don't need to load and shuffle index values to the result code should be.....
2. Simpler.
3. Can be done in ladder.
4. Easier to debug. You will not need the AR registers. Keeping track of what is in changing address registers is challenging.

There are times when I think indirect addressing should be used, this is not one of them. I don't believe you should be using indirect addressing all the time when it isn't necessary. The blkmovs would only need to be executed when changing parts. This code would occupy only a little and very simple logic.
 
Thats a wierd bit of code, I have no idea why some things are being done, I have a feeling whoever wrote that code also is learning how to do it!!

Doing as Peter says may be better if your unsure, if all the data is together then it may be better, if the data is all over the place then indirect addressing is a must.

The bit you wannt to know, indirect addressing. The method here is using AR1 to hold the indirect address, the data format is already set up by the fact that it uses T DBW, this tells the system its a dataword format and uses the open DB.

T DBW[AR1, P#0.0]

AR1 = the data word and P#0.0 is the OFFSET. This method is good if you had multiple words to write to and you just calculate the first word.

For example you want to wrote to DBW 4, 6 and 8, you would insert the offset for the first word into AR1 (I'll explain that bit later on) and then you could access the words in successive instructions such as T DBW[AR1, P#0.0], then T DBW[AR1, P#2.0] and finally T DBW[AR1, P#4.0]. The P# is a pointer offset and in the example it offsets by 0, 2 bytes and 4 bytes.

In your code he does not do this, so he could have coded simpler.

AR1 = address register 1, this is the address pointer.

AR1 was loaded with a byte address, the way the programmer did this was to load a 'M Byte' and SLW4, this means he is restricting the address to between 0 and 15 (Its doubled later on, so between 0 to 30 in words).

To explain what he's doing, the pointer takes the format BYTE ADDRESS.BIT ADDRESS, it is two words long. The format of the bits in the two words are:

mmmmmmmm 00000yyy yyyyyyyy yyyyybbb

where m = memory area (this is not used in the example it is directly programmed as DBW, therefore data block area).

0 = unused

y = byte address

b = bit address

If MW254 held the value 12, then by shifting MB255 (the LSB) he moves the bits left 3, as the right 3 bits are the bit address, then a further left 1 (multiply by 2), therefore the address he would be pointing to would be '24' not '12'.

So T DBW[AR1, P#0.0], would transfer the data to dataword 24.

Now the code!!!!

1. He uses a MW254, when MB255 would have been suffice (note the instruction INC is a byte instruction and would leave MB254 (MSB) unchanged.

2. T DBW[AR1, P#0.0] could have been simpler, if he had stored the address in a double word, say created a DWORD TEMP flag (call it 'ADDRESS', then instead of LAR1, could have had T #ADDRESS, followed by T DBW[#ADDRESS].

3. I have no idea why he saves and restores the STW in between each move.

4. What does he use #conv_akku1 for, he loads data in and never uses it! #conv_akku2 only is transferred into your DW! [and akku2 is only the address pointer?]

How he gets the address in the first place, the contents of DB244.DBW2 is multuplied by 3 and added by 20, therefore the first word will always be 20 minimum (if DBW2 = 0).

In this case as well, the same words (DBW34, DBW36 and DBW38) are always written into words pointed to by the AR1 offsets.


Hope this helps.
 
Last edited:
Just looking again at the code again.

I said he's limited to 0-30, sorry wrong there. He's limited to 0-255 before he multiplies by 2. Although he loads in only the LSB, of course SLW4 he doesn't lose any of that data (its early here).

BUT

The INC instruction would lose info if the number held in MB255 overflowed (I presume the offset would be way below this though).
 
I would have done the same thing as below:

indir.JPG



If DBW2 = 4, then

DBW34 would transfer to DBW((4*3)+20)*2 = DBW64
DBW36 would transfer to DBW(((4*3)+20)+1)*2 = DBW66
DBW38 would transfer to DBW(((4*3)+20)+2)*2 = DBW68
 
yet another 'simpler' way, by using the original method the way it should be used.

ind2.JPG


Don't you hate those little things that keep irritating you, I keep thinking about that silly bit of code, I need help I'm sure.

Am I missing something in what the original is doing, it does look incorrect to me.

The way I look at it DBW34, 36 and 38 never get loaded into the indirect addresses.:confused:
 
PeterW said:
How he gets the address in the first place, the contents of DB244.DBW2 is multuplied by 3 and added by 20, therefore the first word will always be 20 minimum (if DBW2 = 0).

In this case as well, the same words (DBW34, DBW36 and DBW38) are always written into words pointed to by the AR1 offsets.


Hope this helps.

Peter,

Thanks so much for taking the time to look at this code. Maybe I can explain a little better what is going on.

  1. db 253 is the db that is used by the operator panel. DBW66 is the part type value which can be observed and/or changed by the operator.
  2. DB 244, DBW2 is the current part type. In other words, when they are not equal(DBW2 and DBW 66 of different DBs), the saving and recalling code must be done.
  3. To answer your question, "am i missing something?..." I don't know. When I get to work this afternoon I'll send the rest of the code to try to help clarify what is going on.
Also,

I believe that part of why the original programmer did things this way was that it was known ahead of time that we will be adding more and more part types as we pick up new product lines. Also, we have multiple programmers in the plant and it must be done such that a programmer can add a part type and not have to change much in the way of the data handling for the part. The OEM is German and we have many of their machines in the plant. They use this same bit of programming on all of the ones that run multiple parts.
 
I do have trouble with this bit of code:

T MW 254 // ACCU-1 = MW254 ACCU-2 = ?

L DBW 34 // ACCU-1 = DBW34 ACCU-2 = MW254
T #conv_akku1 // = DBW34

TAK // ACCU-1 = MW254 ACCU-2 = DBW34
T #conv_akku2 // = MW254

L STW // ACCU-1 = STW ACCU-2 = MW254
T #conv_STW // Stores the Status Word ???

L MB 255 // ACCU-1 = MB255 ACCU-2 = STW
SLW 4 // Changes MB255 to Pointer ACCU-1 = MB255 as pointer ACCU-2 = STW
LAR1 // and Stores in AR1

L #conv_STW // ACCU-1 = #conv_STW ACCU-2 = MB255 as pointer
T STW // recovers Status Word

L #conv_akku1 // ACCU-1 = DBW34 ACCU-2 = #conv_STW
L #conv_akku2 // ACCU-1 = MW254 ACCU-2 = DBW34

T DBW [AR1,P#0.0] // MW254 transfers to DBW pointed to????

This doesn't make sense to me?? :confused:
 
Last edited:
Peter - in the originally posted code, DBW34 is transferred to #conv_akku1 and MW254 is transferred to #conv_akku2. #conv_akku1 is then loaded before the T DBW[ar1,p#0.0] instruction, so yes it does work.

The front bit of code could be tidied up as well as there is no need to use MW200. I would agree that the original programmer was not familiar with Step 7 STL.

Code:
L DB253.DBW66
L DB244.DBW2
==I
JC =m001

NB: did you know you can use the "code" keyword and simply copy/paste the stl as text instead of as an image. It makes it a lot easier to paste the code into Step7 if you need to run it in the simulator. For example, the orginal code was posted as an image - if I wanted to run this code I would have to type it in myself (and probably introduce a typo). If it was text, I could paste it into Step 7 and run it knowing that it was the code as posted.

NNB: Posted whilst you were adding the previous post !
 
Last edited:
SimonGoldsworthy said:
Peter - in the originally posted code, DBW34 is transferred to #conv_akku1 and MW254 is transferred to #conv_akku2. #conv_akku1 is then loaded before the T DBW[ar1,p#0.0] instruction, so yes it does work.


Aaaah, thats exactly what happenned, I typed it wrong into an FC.

so code

Code:
l #test_this_code_malarky

hmmm better


supprised, aboout the programmer as it originates from our friends in Deutchland.
 
Hey Bri_ZF, I am 99% sure I used to work in the same plant as you are now. I'll bet I even know the OEM of the machines you are talking about. I still stop in the plant once in a great while.

The equipment you are working on is a good way to get extensive training on Siemens. I don't always like the European way of programming S7s, because they don't take advantage of the extensive symbolic possibilities as compared to S5 (such as in your case, where I think it would be a perfect place to group the part type properties and use UDTs instead of shuffling data around word by word), but you can still learn a lot.
 
PeterW said:
supprised, aboout the programmer as it originates from our friends in Deutchland.
Hi Guys
I just have to defend this "German" programmer (just a little bit). As You all know, this original code has made for S5 and "now" somebody has convert this program code to S7. If S5-code includes some indirect parts then the "S5toS7 Converter" converts it like in this example.
As You can see, its not very readable! So dear colleagues, if You have to convert program from S5 to S7 -> clarify those S5 indirect parts and write them again to S7. In the long run, it helps alot You and the enduser.

Pete 🍻
 

Similar Topics

Need the explaination of the code given below... Wgy not adding more than 8 real values.... L P##Measuring_values //Address of...
Replies
3
Views
2,091
I get a weekly email from Siemens Tech Support. It has Tech notes updates etc. This week they have the following example of indirect addressing...
Replies
0
Views
2,455
C
Does anyone know how I can indirectly address data in a datablock in step 7? EG. I have a DB containing multiple 'records'. I would like to...
Replies
1
Views
4,124
I have a question regarding the use of indirect addressing and pointers. Is there a difference between using the SLW3 and multiplying the original...
Replies
9
Views
19,639
Hi, What I need is: I'm writing a function. At the outside of the block I just want the parameter P_OFFSET_BYTE. PIB256 PIB257 PIB258 ...
Replies
2
Views
1,660
Back
Top Bottom