S7 Pointer Issue

cjd1965

Lifetime Supporting Member
Join Date
Apr 2007
Location
UK
Posts
1,659
Hi I am trying to create a block to set a bit in a datablock. My problem is the final Set statment which generates an error.

Esentially FC1 is given an integer value which is the number of the bit to set in DB1



DATA_BLOCK DB 1
TITLE =
VERSION : 0.1

STRUCT
Step01 : BOOL ;
Step02 : BOOL ;
Step03 : BOOL ;
Step04 : BOOL ;
Step05 : BOOL ;
Step06 : BOOL ;
Step07 : BOOL ;
Step08 : BOOL ;
Step09 : BOOL ;
Step10 : BOOL ;
Step11 : BOOL ;
Step12 : BOOL ;
Step13 : BOOL ;
Step14 : BOOL ;
Step15 : BOOL ;
Step16 : BOOL ;
END_STRUCT ;
BEGIN
Step01 := FALSE;
Step02 := FALSE;
Step03 := FALSE;
Step04 := FALSE;
Step05 := FALSE;
Step06 := FALSE;
Step07 := FALSE;
Step08 := FALSE;
Step09 := FALSE;
Step10 := FALSE;
Step11 := FALSE;
Step12 := FALSE;
Step13 := FALSE;
Step14 := FALSE;
Step15 := FALSE;
Step16 := FALSE;
END_DATA_BLOCK

FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
StepNumber : INT ;
END_VAR
VAR_TEMP
ILoopCount : INT ;
END_VAR
BEGIN
NETWORK
TITLE =

OPN DB 1; // open data block
L 0;
T DB1.DBW 0; // Clear the step coils in the DB
L 0; //Load start bit into AR1.
LAR1 ;
L #StepNumber; //which bit (+1)
NEXT: T #ILoopCount; // Loop Counter
+AR1 P#0.1; //increment to next bit
L #ILoopCount;
LOOP NEXT;
S DBX [AR1,P#0.0]; // Set Bit

END_FUNCTION

ORGANIZATION_BLOCK OB 1
TITLE = "Main Program Sweep (Cycle)"
VERSION : 0.1


VAR_TEMP
OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
OB1_PRIORITY : BYTE ; //Priority of OB Execution
OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
OB1_RESERVED_1 : BYTE ; //Reserved for system
OB1_RESERVED_2 : BYTE ; //Reserved for system
OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =

CALL FC 1 (
StepNumber := 2);
NOP 0;
END_ORGANIZATION_BLOCK
 
There's no jump out of the loop. edit: - forget that loop goes down not up šŸ™ƒ

(Why do you have a loop when you only want to set once?) edit: forget that bit

Personally I would use JL for this type of thing.
 
Last edited:
Hi
I am still 'learning'. I used a loop to try and determine which bit to set based upon the integer value.
I thought that the LOOP value was automatically decremented by the PLC.

Open to suggestions,

Cheers
 
I think you need to load the pointer to point to DB1.DBW0, not the L 0.

Something like

L P#db1.dbw0
LAR 1

or

LAR1 P#db1.dbw0


unfortunately I don't have Step 7 at the mo to check which works.
 
OK you are suggesting the pointer should be initialised to the first bit of the datablock, i will try to figure that out

Cheers
 
The "L 0" is ok to set the pointer. But there are better ways to do this. But let's figure out what's going wrong here.

There is a comment where the StepNumber is "Which Bit (+1)". What does that mean? For instance, if you are at Step 10, do you pass in a 10? And do you want to set Step10 to true?

I am sure the error you are getting is due to jumping off the end of the data block.
 
The code as posted does not produce an error, but also it does not set any bits because there is nothing to condition the RLO. Add the SET as below to fix this. With STEP=2 this will then set DB1.DBX0.2 which is Step03 in the DB. Can you confirm that the functionality required is that if STEP=1 then DB1.DBX0.0 should reset etc.

Code:
LOOP NEXT; 
SET
S DBX [AR1,P#0.0]; // Set Bit
 
Hi
Sorry for the vagueness. The general idea is that the StepNumber integer determines which bit is set. All other bits shoud be off except for the required one. This is essentially a 'Data Block Clear' followed by a 'Datablock Bit Set'
The add 1 is because I intend to have the first bit (0.0) to actually mean Step 0 rather than step 1 so, if the StepNumber is 0 bit 0.0 will be active.
My DB names do not reflect this at present so apologies for the confusion.

My error was to forget the SET

Cheers
 
Rather than looping you can just load the step number into AR1 giving the following

STEP=0 SETS DB1.DBX0.0
STEP=1 SETS DB1.DBX0.1
etc.

You can increment/decrement before transferring to AR1 if you want a different relationship.

Code:
	 L	 0
	 T	 DB1.DBW	0				// Clear the step coils in the DB 
	 L	 #StepNumber				 //Load start bit into AR1.
	 LAR1 
	 SET 
	 S	 DBX [AR1,P#0.0]			 // Set Bit

Note also that:

T DB1.DBW0 is actually executed as

OPN DB1
T DBW0
 
If I wished to used a DB as a input block (target for the 16bits) how would i reference that?

How would I modify this to use a db as an input also. I know how to use a block as an input, it is clearing the block data and writing the final bit to the block i am interested in

Cheers
 
If I read you correctly, you want to indirectly access the DW by referencing it as an I/O parameter.

Create an OUT parameter, call it something like STEP and create it as a WORD.

When yoi call the block, you can then assign the address, i.e. DB1.DBW0 to the OUT, STEP.

I'm not sure if you can directly access the OUT from the pointers (I'm sure someone like Simon will answer that).

You could create a TEMP word and call it TEMP_STEP, then in the code

Code:
L 0
T #TEMP_STEP

L P##TEMP_STEP
LAR 1
L #StepNumber
+AR1

SET
S LW[AR1, P#0.0]

L #TEMP_STEP
T #STEP


how I wish I had Step 7 to try this, I believe its in the right direction though.
 
Here's the source code of the block re-written to accept the step number as an integer and the step store as a pointer. Using a pointer for the step store means you can specify a db, local data or static data for the step store.

The StepStore parameter will be given the value DB1.DBW0 for example.

Code:
FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1

VAR_INPUT
  StepNumber : INT ; 
  StepStore : POINTER ; 
END_VAR
VAR_TEMP
  iStepStoreDB : INT ; 
  dwStepStoreAreaPtr : DWORD ; 
  temp_step : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =
	  L	 P##StepStore; //point to parameter in V area of calling block
	  LAR1  ; 
	  L	 W [AR1,P#0.0]; // get db number for pointer
	  T	 #iStepStoreDB; 
	  L	 D [AR1,P#2.0]; //get area pointer for pointer
	  T	 #dwStepStoreAreaPtr; 
	  L	 #iStepStoreDB; //is db=0 ?
	  L	 0; 
	  ==I   ; //if so then no db to open
	  JC	nodb; 
	  OPN   DB [#iStepStoreDB]; //else open the db
nodb: L	 0; //zero the step bits
	  T	 #temp_step; 
	  L	 P##temp_step; //point to step bits
	  LAR1  ; 
	  L	 #StepNumber; //point to step number in step bits
	  +AR1  ; 
	  SET   ; 
	  S	  [AR1,P#0.0]; //step number now set
	  LAR1  #dwStepStoreAreaPtr; //point to result
	  L	 #temp_step; //get temp value with step bit set
	  T	 W [AR1,P#0.0]; //write to result
	  SET   ; 
	  SAVE  ; 
END_FUNCTION
 

Similar Topics

I have a word in some DB which I want to load to AR1 and use as a pointer. In order to do this I need to write L DBxy.DBW xy SLD 3 LAR1 I...
Replies
3
Views
533
I am trying to access the value of a pointer via OPC UA in Codesys. I can share it directly and in a struct but I cant access the value of it when...
Replies
5
Views
1,602
Why does my deconstruction of the input pointer only work with its own instance DB not inside the multi instance FB...See .doc The pointer at the...
Replies
8
Views
2,339
Hi All, in many library function of TiaPortal some data must be write using the pointer format........ eg.: P#DB90.DBX0.0 WORD 10 is it...
Replies
5
Views
2,818
I have a very strange issue and I cannot figure out why it is not working. I read input of type pointer and store it to local temp type any. I...
Replies
4
Views
1,926
Back
Top Bottom