Siemens S7 SCL-rookie

augenstern

Member
Join Date
Nov 2007
Location
Germany
Posts
15
First of all: hello to all the people in that board!

I'm a S7-SCL neewbie (programming practice in C/C++ for now over 20 yrs, though)

I'm really badly miss pointer and other fine things of C.

One of my problems:

I have to use ANYPOINTERS in SCL. Well how it works is quite fine, but practical usage is pretty hard.

I could use a DB for every used datastruc, but for some reasons I have to be very cheap in using DBs.

So I set up one (fairy large) DB that contains all of my data.


Problems:
- how can I get the
startadress of some data within the DB at RUN-Time?
- how can I get e.g. the size of a byte-array at RUN-Time

I'm talking about such handy things like offsetof() or sizeof()
in C.

Of course, I could code this at compile-time, but I need to dynamically get those things at RUNTIME!

Is that possible, at all?

example:

anyarray : ARRAY[0..127] OF BYTE;

i := sizeof(anyarray) ???
 
Here are implementations of sizeof and offsetof:

sizeof returns the number of elements in the array. If you want the number of bytes, it can be done.

offsetof returns the byte offset of the passed array element from the start of the array.

This should get you started.

Code:
FUNCTION FC90:INT
//sizeof
VAR_INPUT
	pArrayName:ANY;
END_VAR
VAR_TEMP
	pAny:ANY;
MyAny AT pAny:STRUCT
	ID:BYTE;
	TYP:BYTE;
	NUM:INT;
	DBN:INT;
	PTR:DWORD;
	END_STRUCT;
END_VAR
BEGIN
pAny:= pArrayName;
FC90:=Myany.NUM;
END_FUNCTION 
 
FUNCTION FC91:INT
//offsetof
VAR_INPUT
	pArrayName:ANY;
	pArrayElement:ANY;
END_VAR
VAR_TEMP
	pAny:ANY;
MyAny AT pAny:STRUCT
	ID:BYTE;
	TYP:BYTE;
	NUM:INT;
	DBN:INT;
	PTR:DWORD;
END_STRUCT;
dwOffset1:DWORD;
dwOffset2:DWORD;
diOffset1:DINT;
END_VAR
BEGIN
pAny:= pArrayName;
dwOffset1:=MyAny.PTR AND DW#16#00ffff;
pAny:= pArrayElement;
dwOffset2:=MyAny.PTR AND DW#16#00ffff;
FC91:=WORD_TO_INT(DWORD_TO_WORD(DINT_TO_DWORD( DWORD_TO_DINT(dwOffset2) - DWORD_TO_DINT(dwOffset1))))/8;
;
END_FUNCTION 

FUNCTION_BLOCK FB90
//Test block
VAR
 MyArray : ARRAY[0..21] OF int;
 iSizeOfMyArray:INT;
 iByteOffset:INT;
END_VAR	
BEGIN
iSizeOfMyArray:=FC90(pArrayName:=MyArray);
iByteOffset:=FC91(pArrayName:=MyArray,pArrayElement:=MyArray[13]);
END_FUNCTION_BLOCK
 
Thank you, L D[AR2,P#0.0]

Hi, L D[AR2,P#0.0],

I will need quite a time a understand your code!

But thanks anyway :)

What I need additionally is:

How can I get the offset of a data-variable from the beginning of DB?
 
Here's an example for getting the byte offset for a named variable in a global DB. "DBData" in the symbolic name for DB1 in my example.

Code:
FUNCTION FC92:INT
//byteoffset
VAR_INPUT
	pVariableName:ANY;
END_VAR
VAR_TEMP
	pAny:ANY;
MyAny AT pAny:STRUCT
	ID:BYTE;
	TYP:BYTE;
	NUM:INT;
	DBN:INT;
	PTR:DWORD;
END_STRUCT;
dwOffset:DWORD;
END_VAR
BEGIN
pAny:= pVariableName;
dwOffset:=MyAny.PTR;
FC92:=WORD_TO_INT(DWORD_TO_WORD(dwOffset))/8;
END_FUNCTION 
 
FUNCTION_BLOCK FB90
//Test block
VAR
MyArray : ARRAY[0..21] OF int;
iSizeOfMyArray:INT;
iByteOffset:INT;
END_VAR 
VAR_TEMP
iByteOffsetFromStartOfDB:INT;	 
 
BEGIN
iSizeOfMyArray:=FC90(pArrayName:=MyArray);
iByteOffset:=FC91(pArrayName:=MyArray,pArrayElement:=MyArray[13]);
iByteOffsetFromStartOfDB:=fc92(pVariableName:="DBData".iData13);
END_FUNCTION_BLOCK

EDit: Note that due to the order of the arithmetic I have performed, the largest offset that can be used is byte 8196 - to correct this, the divide by 8 should be done on the dint.
 
Last edited:
L D[ar2,p#0.0]

Huuh, L D[AR2,P#0.0]!

Thank you, but gimme me some time to walk thru your code!

I dont understand it at all. Hard stuff!

:)
 
Have you used the debugging facility in SCL ? you can monitor the code as it is executing, this certainly helps when walking through new code. I use PLCSIM instead of a real plc most of the time.
 
Hi, L D[AR2,P#0.0],

Hi, L D[AR2,P#0.0],

to be honest, I ain't familiar with SCL and the S7 yet - but I'm working on that :)

Currently, I'm messing around with a S7 with 314 CPU and CP.

You ask if I use the debugging facility of SCL?
Yes I use it - but after setting 5 breakpoints in my test-code I didn't work any more ....

I gonna check what this PLCSIM is about ....

Thank you again!
 
Hi, L D[AR2,P#0.0],

Hi, L D[AR2,P#0.0],

frankly, I'm a bloody rookie to the plc- and s7 world at all.

I'm familiar with realtime-programming ( C ) using RT-OSes and C/C++ under Windows environment.

My boss wants me to port some existing piece of software (written in C) to the S7 (as many of our customers use it).

So, right now, I'm learning (by doing and reading, of course).

Today I will check out your code pieces and if they work they will be of great help!!!
 
Hi, L D[AR2,P#0.0]

Hi, L D[AR2,P#0.0],

great!

I checked and single-stepped your code, and: IT WORKS!

Great :)

Only one point: FC90() does not return the size (in bytes) but the number of elements (in case of an array).

But anyway, it is a great help!

I had a 2 day-SCL-training from an Siemens-expert. But I learned more reading thru the posts in this an some german s7-forum!

btw: is there any way to simulate a #define stmt of C or global CONSTs?

I want to avoid constructs like "bla : array[0..127] of INT" but I'd rather "bla : array[0..MAX] of INT"

( Of Course the sizeof() would do the job )

Your are my guru, L D[AR2,P#0.0]!
 
Here's a revised FC90 that now returns the number of bytes:

Code:
FUNCTION FC90:INT
//sizeof returns nummber of bytes or -1 if type not recognised
VAR_INPUT
	pArrayName:ANY;
END_VAR
VAR_TEMP
	pAny:ANY;
MyAny AT pAny:STRUCT
	ID:BYTE;
	TYP:BYTE;
	NUM:INT;
	DBN:INT;
	PTR:DWORD;
END_STRUCT;
iType:INT;
END_VAR
BEGIN
pAny:= pArrayName;
iType:= CHAR_TO_INT(BYTE_to_char(MyAny.TYP));
CASE iType OF
	2,3: FC90:=Myany.NUM; //byte, char
	4,5,9,12: FC90:=MyAny.NUM * 2; //word, int, Date, s5time
	6,7,8,10,11:FC90:=MyAny.Num * 4; //dword, dint, real, TOD, Time
	14:FC90:=MyAny.Num * 8; //DT
ELSE
	FC90:=-1;
END_CASE;
END_FUNCTION
 
Hi, L D[AR2,P#0.0]!

Hi, L D[AR2,P#0.0],

once again: thank you so much 4 your code!

It really helps me a lot and helps me to understand SCL much better!

The Siemens-guy I received the training from should feel embarassed .....

I hope I don't bother you but I'm sure I will have more questions in the future .....

Thanks, my Guru :)
 
Hi augenstern.

I am interested in knowing what the application/problem is.
From your posts on sps-forum.de I get the impression that your problem is that you worry about that changing absolute adresses shall affect your code.
In other words you are really not after dynamic memory allocation during runtime, but merely that you code takes symbolic modifications into account at design time.
Is that correct ?
 
Hi JesperM

I indeed posted my questions in the german forum.

My points are:
(1) I do want to avoid 'hardcoded' expressions i.e. I want to avoid data-structs that force me to walk thru my code if I change their sizes e.g. of arrays. Or when DB-Numbers change.
(Imagine: bb : array[0..MAX] is easier to maintain as bb : arry[0..127] )

(2) My code will be run on S7 alltogether with other code, (programmed by customers). I don't know nothing about that code (what it does, how it is structured and so on). As u can imagine there will be some conflicts in DB-/FC-/FB-numbers. To keep the number of conflicts as low as possible (and therefore reduce possible problems) I want to keep the number of 'my' DBs as low as possible i.e. I want to put all my date in one or two DBs max. This however needs that I can fill Anypointers with correct data (offsets, lengths...) which was my original problem.

The Siemens training engineer led me thru some example code (using ftp and ag_send/ag_receive) where he used DBs for every data-struct e.g. ftp-buffer and others. This made it easy for him to fill the Anypointers - but he also used absolute addresses and DB-numbers which make code-maintenance a difficult task.
I believe he was not the right guy to teach S7 programming techniques ....

I try to keep maintenance cost low, and so I try to do run-time calculations or symbolic use of data as much as the prog-language allows and supports (and it makes sense).


Greetings!

I like this forum :)
 
How many lines of C code do you have to port ?

My suggestion is to continue the port as a learning exercise. What you will produce will be messy but, you will know an awful lot more about S7 and SCL. Throw away the first implementation and then start again.
 

Similar Topics

Hello, When you want compare values of an array to a range of numbers is it a right way to do that? FUNCTION ADD VAR_IN_OUT A:ARRAY[1..50]...
Replies
5
Views
2,045
Hi All, I need to try and convert some code from Siemens SCL (TIA16) over to Allen Bradley RS5000. I have attached an image of the SCL and what...
Replies
10
Views
4,025
in the scl code written in screenshot Line 1 condition is false but still the program checking the line 2 condition and says it is true i had...
Replies
3
Views
1,736
I am new to PLC programming. Is there a standard way to incorporate alarms / warnings / events such as the exceptions in C++ or Java where you can...
Replies
5
Views
1,934
Hello All, I am new to programming with Tia Portal and I am having difficulty with something that we have found "easy" in other programming...
Replies
3
Views
2,334
Back
Top Bottom