Siemens PLC Indirect addressing

naturephoenix

Member
Join Date
Jan 2015
Location
Vienn
Posts
181
Hello guys,


This works:


L P#DBX 30.0
LAR2


But I need "DBX 30.0" to be input parameter to the function.


I made pTag variable with data type Pointer and it is input to my function.


On a function call, input pTag is P#DBX30.0


But
L P##pTag
LAR2


does not work. What is wrong over here?
 
Last edited:
Have you value 30 (Dint) on pTag?

If so you need multiple with 8 or shl 3, otherwise pointer is pointing to wrong address.
 
L P##pTag


Loads the accumulator with the pointer to ptag, not the contents of ptag which is actually 6 bytes and not loadable into the accumulator.
 
Guys this is what I'm trying to make but it is not going:


I have a Data Block DB2 which consists of 576 Tags. Each TAG is 1 Alarm. Each TAG is aslo UDT structure called DT_SIGNAL:
UDT looks like this:
Code:
EN   BOOL   TRUE       

Alarm   BOOL   FALSE       

Alarm_temp   BOOL   FALSE       

STR   BOOL   FALSE       

NSD   BOOL   FALSE       

QSD   BOOL   FALSE       

MBD   BOOL   FALSE       

GBD   BOOL   FALSE       

ESD   BOOL   TRUE       

SMS   BOOL   FALSE       

 INF   BOOL   FALSE
I want to make FB which checks inside DB2 whether 2 bits in each TAG (Tag is UDT structure) are giving logical true on AND gate.For example (DB2.DBX0.1 AND DB2.DBX0.5).If (DB2.DBX0.1 AND DB2.DBX0.5) gives logical true I consider Alarm activated. If so(if they are enabled) increment counter. So output of my FB needs to consists output variable which tells how many alarms of certain type is activated.




INside FB in static variable I want to also save inside an array something like this:
AlarmNumbers[0] = 10
AlarmNumbers[1] = 20

AlarmNumbers[2] = 30

AlarmNumbers[3] = 40
...
THis would mean that Alarm No. 10 (out of 576) is activated(means DB2.DBX18.1 and DB2.DBX18.5) gave true.

Here is FB structure:
IN:
dbBlock : Block_DB
pAlarm : POINTER
pType : POINTER
dbInctanceNo : Block_DB


OUT:
AlarmTypeActive : BOOL
AlarmTypeCount : INT


STAT:
AlarmNumbers : ARRAY[0..999] of int


TEMP:
Loopsize : INT
AlarmIDNo : INT
InnerLoopSize : INT
MAxAlarmNo : INT
noOfActAlarms : INT




Here is mine try:


Code:
      L     0
      T     #noOfActAlarms              // Alarm count to be 0 at begging

// Open Alarm DB
      OPN   #dbBlock
      L     DBLG
      L     2
      /I    
      T     #MaxAlarmNo                 // Max Alarm NUmber is  Byt No. / 2


      L     P##pAlarm                   // Take local FB address from pAlarm 
      LAR1                              // Write address in address registar AR1
      L     D [AR1,P#2.0]               // Take 4 BYTES starting from second BYTE, 
      LAR2                              // Write address in address registar AR1

      L     P##pType                    // Take local FB address from pType 
      LAR1                              // Write address in address registar AR1
      L     D [AR1,P#2.0]               // Take 4 BYTES starting from second BYTE,
      LAR1                              // Write address in address registar AR1




      L     #MaxAlarmNo
Lp:   T     #LoopSize                   // For Loop


      OPN   #dbBlock
      A      [AR2,P#0.0]                // Alarm & Alarm Type
      A      [AR1,P#0.0]
      JCN   end

      L     #noOfActAlarms              // Increment active Alarms of certain Alarm type
      L     1
      +I    
      T     #noOfActAlarms              //#noOfActAlarms is also Alarm index into Array 


      L     #MaxAlarmNo
      L     #LoopSize
      -I    
      T     #AlarmIDNo                  // Alarm ID Number

// Saving Alarm ID Number into corresponding array index AlarmNumbers[]



      L     P#0.0
      LAR1  

      L     #noOfActAlarms
      L     2
      *I    
Lp2:  T     #InnerLoopSize
      OPN   #dbInstanceNo
      +AR1  P#2.0
      L     #InnerLoopSize
      LOOP  Lp2

      L     #AlarmIDNo
      T     W [AR1,P#0.0]


//Reset pointers for outside LOOP 

      L     P##pAlarm                   // Take local FB address from pAlarm 
      LAR1                              // Write address in address registar AR1
      L     D [AR1,P#2.0]               // Take 4 BYTES starting from second BYTE, 
      LAR2                              // Write address in address registar AR1

      L     P##pType                    // Take local FB address from pType 
      LAR1                              // Write address in address registar AR1
      L     D [AR1,P#2.0]               // Take 4 BYTES starting from second BYTE,
      LAR1                              // Write address in address registar AR1



end:  +AR2  P#2.0
      +AR1  P#2.0
      L     #LoopSize
      LOOP  Lp

      L     #noOfActAlarms              // Temp, get full number of alarms
      T     #AlarmTypeCount             // save Temp variable to the OUTPUT variable

// If is active number of Alarm <> 1, set  #AlarmTypeActive
      L     #AlarmTypeCount
      L     0
      <>I   
      S     #AlarmTypeActive
 
Last edited:
I have tried to describe the task you want to perform:

There is an existing DB with an Array structure defined by a UDT. The UDT only contains BOOLs.
Check all BOOLs withing each structure if 2 BOOLs or more are set.
Also, generate a list of active alarms, based on the above condition (2 or more BOOLs set). The list is an array, with each array entry pointing to the no of the DB Array member with an active alarm.
You dont write how many entries you want in the list.
You dont write what to do if there are more active alarms than what the list can fit.

My take:
This is a job for SCL ! If this is STEP7 Classic (S7-300/400) it is dead easy in SCL. In TIA (S7-1200/1500) you can do array indexing in LAD and FBD as well as in SCL. But I would use SCL anyway.

Make the data available by an input-pin on the FB, defined as ARRAY[0..575] of Alarm_data_type.
Then make a FOR-NEXT loop that scans the array, and updates the list of alarms by the condition 2-or-more BOOLs are set. Each time an alarm is encountered, a counter is incremented. The counter points to the array element in the alarm list that needs to be set. If the counter reaches the maximum of entries in the alarm list, no further bits are set. Maybe an alarm is generated.
Finish with a FOR-NEXT loop that resets the remaining entries in the alam list, this so they dont get set forever.

Everything is symbolic, except for the array sizes used by the FOR-NEXT loops, these you code manually.
 
A disadvantage with using pointer-based logic for something that looks like it is a background task, and includes looping through large arrays, is that the code execution may be quite long. This can be a problem on some of the less-performant CPUs.

Therefore my take #2:
Same as before, but instead of passing the array via an input-pin, the FB access the Alarm-DB directly.
For example like this:
Code:
FOR i=0 to 575 DO
  #alarm_is_active := ("alarm_db".var[i].alarm AND "alarm_db".var[i].alarm_mem) OR ("alarm_db".var[i].alarm AND "alarm_db".var[i].STR) OR .....
This is in principle less easy to maintain since you have to 'know' the structure of the alarm-DB. But still it is trivially easy.

edit: It is quite clever to let the 2 arrays be a shared-DB and an instance-DB. The SCL compiler is clever enough to setup all the DB accesses as access to already open DB or DI. So this makes the code execution faster.
 
Last edited:
In order to resolve this task, I made litle test.
Trying to first store addresses of some DB inside temp variables of FB. after that I just read data from certain addresses.


It works. But when I want to save values to the FB out variables, PLC goes to STOP.


val_B, val_I, val_R are FB outputs (Bit, integer and real)
I think it goes to stop cuz it is already OPENED another DB.


Not sure how to skip this issue.



Code:
      L     #dbNum
      T     #tmpDBNum


      OPN   DB [#tmpDBNum]

      L     P##pAd_B                    
      LAR1                             
      L     D [AR1,P#2.0]                
      LAR2                              
      T     #Address_B




      L     P##pAd_I
      LAR1                              
      L     D [AR1,P#2.0]               
      LAR2  
      T     #Address_I

      L     P##pAd_R
      LAR1                              
      L     D [AR1,P#2.0]                
      LAR2  
      T     #Address_R


// Take values 
      A     DBX [#Address_B]
      =     M     80.0

      =     #val_B    //It goes to stop cuz of this

      L     DBW [#Address_I]
      T     MW   100
//      T     #val_I   //It goes to stop cuz of this

      L     DBD [#Address_R]
      T     MD   104

//     T     #val_R   //It goes to stop cuz of this


// 


// Adding addresses

      L     P#DBX 8.0
      L     #Address_B
      OD    
      LAR1  
      T     #Address_B_1

      L     P#DBX 8.0
      L     #Address_I
      OD    
      LAR1  
      T     #Address_I_1

      L     P#DBX 8.0
      L     #Address_R
      OD    
      LAR1  
      T     #Address_R_1

//; 



//Reading 2

      A     DBX [#Address_B_1]
      =     M     86.0

      L     DBW [#Address_I_1]
      T     MW   110

      L     DBD [#Address_R_1]
      T     MD   114
 
Last edited:
Once you have modified AR2 you cannot access any variables from an FB's interface except temporary data.
 
Can't you code 3 several FC blocks and loop only for AR1?


Something like


L #0
T #Alarms_cnt




OPN DB30
L P#0.0
LAR1
A DBX [AR1,P#0.1]
= #temp_bit1
A DBX [AR1,P#0.5]
= #temp_bit2


A #temp_bit1
A #temp_bit2

= #alarm_active


A #alarm_active
(
L #alarms_cnt
L #1
+D
T #alarms_cnt
)
+AR1, #P2.0 // AR1 pointing to DBX 2.x



2nd check
A DBX [AR1, P#0.1]
= #temp_bit1
A DBX [AR1,P#0.5]
= #temp_bit2


...


Still, why you want to code this with STL when there is SCL
 
Last edited:
Example code attached.
OB1 contains a for loop to call the alarm processing (FC1) for all the alarms - [0..10] in my example.
FC1 copies the current alarm data from DB1 to a temp copy of the Alarm structure, the alarm processing can thus be coded using the UDT names, not hardcoded addresses.
The project is in English not Croation.
 

Similar Topics

Hi, I have a DB in my program with all the alarms of a machine, but the machine is divided in stations. So I want to check if any station is with...
Replies
2
Views
2,079
The past week we received a new piece of equipment from Germany which utilizes siemens controls. Typically in our company we use A.B. controls for...
Replies
4
Views
54
i have two plc 1. s7-1212dc/dc/dc ip; 192.168.0.1 2. s7-1500 1513-1pn ip; 192.168.3.2 i need to get data from plc1 to plc2. any idea how to do...
Replies
5
Views
100
Good morning fellow sea captains and wizards, I am being asked to do the above and obtain 4 values from each slave, I know about the MRX and MWX...
Replies
32
Views
715
Hey guys, I have to take an upload of a program on an S71200 PLC to change a hardware config option and then redownload the program with this...
Replies
3
Views
111
Back
Top Bottom