Struggling with S7 STL...

uptown47

Lifetime Supporting Member
Join Date
Feb 2008
Location
Over there, next to those boxes
Posts
1,146
Hi all,

(Firstly, I did post a similar topic yesterday but I felt that this is sufficiently removed from my original question to warrant a new topic)

I've been trying to write a block to basically take in a set of 'words' check to see which bits are on and then load an appropriate value into an output word.

I'm going to use the output word to display a message on a HMI.

The tricky bit (for me) is that, if there is more than 1 bit on in the input words, I want to load in the different values to the output word with a 2 second pause between each.

For instance... input word is MW206 and bits M207.0, M207.2 and M207.7 are on (Estop pressed and Guard door open). I want to make my output word equal to '1' for a couple of seconds and then equal to '3' then to '8', then back to '1' etc etc....

I've also been using this as a learning aid to STL as I'm trying to improve my code writing in STL.

I've created an FB that allows me to denote whether the alarm conditions are in a datablock or markerwords. The FB then counts through the 'bits' and if one of them is 'on' it passes the relevant value to the output word.

Unfortunately my timer isn't working. The reason is that the timer seems to be always 'on' i.e. it isn't seeing the rising edge on its enable input. I'm not sure why?

I've tried putting a one-shot on the enable of the timer and I've tried ensuring that "MESS_ON" (the bit that brings on the timer) is Reset in the code but to no avail..

I wondered if someone could cast an experienced eye over my code and answer the following questions (all or some)...

1) Why is my timer enable staying 'high' all the time? ie. why is T71 not working??

2) Why is it that I can indirectly address a TEMP type from the Variable Declaration Table but not a STAT type. i.e. The software wouldn't let me write:
Code:
A M[MESSAGE_POINTER] // THIS IS A 'STAT' TYPE
... but it would let me write...
Code:
A M[TEMP_MESS_POINTER] // THIS IS A 'TEMP' TYPE
???

3) If you are able to get your head around what my code is doing could you let me know if I'm making any glaring errors or writing the code in an overly complicated way? Basically, could you suggest ways to improve the code or techniques that would make it easier to do the same thing in the future (help/advice/constructive criticism etc). I started by trying to use "Area Pointers" but then got bogged down with that method.

I've attached the FB in a 'library' file that you can 'retrieve' I tried to attach the code to this post but it wouldn't let me post it for some reason. I'll try and post it again in the reply box below.

Many thanks for any help you can give me.

Cheers

;-)
 
It still won't let me post the source (it's maybe too long for the post??). I've attached it as a text file if you would prefer to look at that instead of the retrieving the library.

Many thanks

;-)
 
You cant use stat with indirect, you need to use temp. Copy to temp before use if you need to use stat. That just is something u cant do, blame siemens :)
 
Last edited:
You cant use stat with indirect, you need to use temp. Copy to temp before use if you need to use stat.

Hi TU,

I ended up doing that (copying from STAT to TEMP before use) but I wondered if there was a reason for this?

Thanks for the info though, glad to hear that it's a restriction in the software and not something I was doing wrong.

;-)
 
I dont have time right now to go trough your code (tomorrow i have) but i bet ld or jesper (or someone else) will get it before ;)
 
I dont have time right now to go trough your code (tomorrow i have) but i bet ld or jesper (or someone else) will get it before ;)

I'm still working on it myself so I'm hoping I may be able to crack it but even if I do I'd still really appreciate your advice / comments / constructive criticism about the code (i.e. question 3 above).

It's frustrating because I can see what the problem with the code is (#MESS_ON isn't going 'low' and allow the timer to restart) but I just can't fix it....

A cup of coffee to clear my head and then back into it I think...

;)
 
Right... I've got it working but I had to go right round the houses in order to do it....

Here's the pertinent piece of code that is now working:
Code:
TIME: L     #MESS_COUNT
      T     #OUTPUT_MESS_WORD
      L     #OUTPUT_MESS_WORD
      L     #TEMP_MESS_WORD
      <>I   
      S     #NEW_MESSAGE_CODE
      L     #OUTPUT_MESS_WORD
      T     #TEMP_MESS_WORD

REDO: AN    #NEW_MESSAGE_CODE
      L     S5T#2S
      SE    T     71
      A     #NEW_MESSAGE_CODE
      JC    ATT1
      R     #NEW_MESSAGE_CODE
      BE    
ATT1: R     #NEW_MESSAGE_CODE
      JU    REDO

You can see that in order to get it working I had to pass through the Timer (T71) with its enable off first and then loop back and pass through it again with the enable on.

Phew!!

As per my original question I would really appreciate some pointers with this code as to where I could make it easier to read / more efficient / generally better. I'm sure I've really over-complicated this but, at the level of knowledge I'm at right now, this is the best I can do so far.

Many thanks for any and all the help / advice you can give me.

Cheers

;-)
 
First network is where the issue is.

A T 71
BEC

Never ever ever ever ever ever ever jump over or end a block when that timer is processed after the BE(C) or JU/JC.

You jump over the code not needed, but you do keep on scanning the piece of code treating the timer.
 
Peter,

I've just tried moving the Timer to the first network and it's working a treat.

Now I've got:
Code:
A #MESS_ON
L S5T#2S
SE T 71
A T 71
R #MESS_ON

This is working fine and is a lot clearer than my last effort. Thanks for the advice.

;-))
 
First network is where the issue is.

A T 71
BEC

Never ever ever ever ever ever ever jump over or end a block when that timer is processed after the BE(C) or JU/JC.

You jump over the code not needed, but you do keep on scanning the piece of code treating the timer.

That makes sense (now) Jeebs, thank you for the advice.

;-)
 
It's a common mistake and most people don't get it right away, best to point it out directly when spotted. It'll save you lots of time and frustration in the future.
 
This is what came to my mind first, that would work with any input type.

Code:
FUNCTION_BLOCK "FindTrueBits"
TITLE =
VERSION : 0.1


VAR_INPUT
  Bits : ANY ;    //pointer to bit area to check    
END_VAR
VAR_OUTPUT
  BitNum : INT ; //zero if no bit is true    
END_VAR
VAR
  j     : INT ;        
  delay : "TOF";            
END_VAR
VAR_TEMP
  dbnum, i, k : INT ;
  pdatain : DWORD ;    
END_VAR
BEGIN
NETWORK
TITLE =


//execute delay timer
      CALL #delay(PT:= T#10S);

      SET   ; 
      R     #delay.IN; 

//if delay has not passed, dont find next bit.
      A     #delay.Q; 
      BEC   ; 

//look for datatype and amount of bits to check
      L     P##Bits; 
      LAR1  ; 
      L     W [AR1,P#4.0]; 
      T     #dbnum; 
      L     B [AR1,P#1.0]; 

      JL    err; 
      JU    err; 
      JU    bool; //bool
      JU    byte; //byte
      JU    err;  //char
      JU    word; //word
      JU    word; //int
      JU    dwor; //dword
      ju    dwor; //dint 

//datatype error
err:  L     9999; 
      T     #BitNum; 
      CLR   ; 
      SAVE  ; 
      BE    ; 

bool: L     W [AR1,P#2.0];  
      T     #i; 
      JU    find; 

byte: L     W [AR1,P#2.0]; 
      L     8; 
      *I    ; 
      T     #i; 
      JU    find; 

word: L     W [AR1,P#2.0]; 
      L     16; 
      *I    ; 
      T     #i; 
      JU    find; 

dwor: L     W [AR1,P#2.0]; 
      L     32; 
      *I    ; 
      T     #i; 

//load pointer to area to check bits from and save it
find: L     D [AR1,P#6.0]; 
      T     #pdatain; 

//open datablock
      OPN   DB [#dbnum]; 

nodb: L     #i; 
loop: T     #k; 

//calculate next bit to check, exploit that next bit to check
//is same as bit count from 1->
      L     #pdatain; 
      LAR1  ; 
//continue from last bit that was checked, roll over when max reached
      L     #j; 
      L     #i; 
      MOD   ; 
      +AR1  ; 
      L     1; 
      +I    ; 
      T     #j; 
//if bit is true, exit loop
      A      [AR1,P#0.0]; 
      JC    foun; 
//loop trough max number of bits
      L     #k; 
      LOOP  loop; 
//if none found true, load 0 to out and exit
      L     0; 
      T     #BitNum; 
      JU    ok; 
//if bit found true, load bit num to output, start delay to show bitnum
foun: L     #j; 
      T     #BitNum; 
      SET   ; 
      S     #delay.IN; 
ok:   SET   ; 
      SAVE  ; 
      BE    ; 
      
END_FUNCTION_BLOCK
 
Two words come to mind when using indirect addressing with FB parameters:

m u l t i p l e
i n s t a n c e
 
Thanks for the code example Turpo. Going to fire it up in the simulator and see if I can get my head around it. It's code like that that really helps me learn new ways of doing things so a really big thank you for taking the time to post it here ;-)

LD, I've heard the words "multiple instance" many times and sometimes I think I understand exactly what it means and then other times I read something which completely undermines my understanding. I'll dig out my Hans Berger book later if I get chance and try and read more about it.

;-)
 

Similar Topics

Hi There, I have couple of Omron PLCs connected on my kepserverex and my intouch reads data from kepserverex. I have been observing that roughly...
Replies
4
Views
130
Good Morning , I've taken on a job that is truly over my head with a engineering group. The standards of Rockwell programming is much more...
Replies
15
Views
7,030
I'm struggling with some device net issues. I am using a AB SLC5/03 processor and a 1747-SDN card supplying a network with 7 FlexIO ADN adapters...
Replies
0
Views
1,310
Good Evening , I'm sorry. so many PLC concepts I still struggle with. I need to move some 8 digit numbers from a SLC 500 5/05 processor to a...
Replies
12
Views
3,714
Afternoon all I am having a few problems with scaling a thermocouple. I'm using a TM221CE40R with a TM3TI8 input card and a type K thermocouple...
Replies
4
Views
2,727
Back
Top Bottom