Problem with FC's Not executing

arkansascontrols

Lifetime Supporting Member
Join Date
Jan 2008
Location
Arkansas
Posts
112
Ok, I've been battling with this all morning and I've finally come to the conclusion that some of my FC's are not being exectued. Here is the scenario;

I have a Function that begins by reading real_array[1] value (via an FC call) then adds the value to a Memory_Real then scales the result and writes it back out to Different_real_array[1] (via a different FC call). Then steps to the next element of the array and repeats until it reaches the last element of the array (8 elements total)

The primary function is continuously running via an unconditional call from OB1, (however jumps out if the enable_bit is not set)the two subsidiary functions (Read Array Real) and (Write Array Real) are not in OB1, but are called as needed from the primary function.

I've confirmed values are being written to Real_Array (via HMI)but the primary function is not reading the values or writing the computed values to the second array. Can anyone explain this to me? Surely the FC's don't have to be continuously called from OB1 in order to work?

Eric
 
From the start of OB1, program flow is linear and only blocks that are called as part of the program flow are executed. Any block call that is in a block that is not being called will not be executed.

I hope this answers your query - without seeing your code it is quite difficult to imagine the scenario you are describing.

When you have one FC being called from many places and you want to monitor the block for a particular call, a quick method is to duplicate the FC and then call the duplicate FC from the place you want to check.

There are tools provided to set-up the calling path for monitoring blocks as well as single stepping (this has to be in STL though)
 
Last edited:
FC Calls

LD,

Here is the scenario;

Function ZBA (Zone Bias Adjust) takes my furnace setpoint, which is scaled 0-1372 for Type K thermocouples, from the Current Recipe DB.

There are 8 'Zones' for heating. Each of the 8 zones is controlled by a PID Loop. The SP_INT for each of the loops has a valid range of 0 - 1000.

So I take the Zone Bias Value (Range from -100 to 100) for each zone and add it to the temp_setpoint (0-1372). I take the sum of these and divide by 1.372 for my 0-1000 and write the value to an array of 8 elements 1 for each loop. If the Zone Biasing is Enabled I want to read each Zone Bias Value, do the math and write the value to the corresponding Array that I'm using for my SP_INT, if Zone Biasing is not enabled I just take the Furnace Setpoint and divide by 1.372 and write it to all 8 elements.

So Function 'ZBA' runs is called continuously from OB1 with no permissives.

RaR and WaR are called from ZBA.

See attached code.

I had to start the furnace this morning and since I couldn't get this working I had to scrap it and write direct addressed logic for each of the 8 zones in each of the two conditions, but I'd like to get my indirect addressing working properly as there are dozens of places throughout the program where similar procedures occur and this will simplify and reduce my code considerably.
 
Code:
 L	 B [AR1,P#0.0]; 
 L	 B [AR1,P#1.0]; 
 T	 #iType;

This doesn't work, you are loading only the second byte into iType.

it needs to be

Code:
L W[AR1,P#0.0);
T #iType;
 
The FCs that do the real array accesses (which were based on the integer versions) contain a coding error.

For the array write you have:

Code:
	 L	 #rDataToWrite
	 T	 W [AR1,P#0.0]

You are reading a real (4 bytes) but writing to a word (2 bytes)
Correct it as follows.

Code:
	 L	 #rDataToWrite
	 T	 D [AR1,P#0.0]

Similarly for the array read:
Code:
	 L	 W [AR1,P#0.0]
	 T	 #rResult

replace with
Code:
	 L	 D [AR1,P#0.0]
	 T	 #rResult

Peter - note that iType is not being used in these FC's
 
Uh hmmmm

Uh, don't I feel stupid. Thanks for not brow beating me over that little oversight guys. I picked over those routines I don't know how many times and never caught that. I'm sure that was it, I won't be able to test till Monday as the Furnace is up and running and I'm planning on sleeping in tomorrow after this past 80+ week. But at least I won't be stuck on this problem over the weekend.

I wish everyone a pleasant weekend. And as much as I've grown to like you guys, I hope I don't have to bother you again too soon.

LD is thinking (yeah right!). I guess I'm buying the beer for the next two months LD.

Eric
 
Yes. Actually this morning, the Sun really is shining and the sky looks reasonably clear, probably a bad omen, I'm hoping it doesn't mean the furnace is going explode or something.
 
Eric - Please find attached your blocks re-coded. There is nothing wrong with them, I've just given you an optimised alternative.

The array read/write functions originally come from a more general function and certain data from the any pointer is not used so I have removed it to make the blocks shorter.
For your zone bias block I have used the Loop instruction and removed duplicate code. Note that the result of arithmetic operations and transfers is left in accu1 so you don't need to load it again after the operation.

Regards, Simon
 
Simon,

Thank you very much for your effort on this, and for the opportunity to learn from your examples. If I might be so bold as to impose upon you for a little clarification it would greatly aid me in a better overall understanding of Siemens.

In the First logic operation of my original code for the Zone Biasing Function I began by checking to ensure that the loop_counter wasn't already initialized. I did this because I am uncertain about the logistics of code execution in Siemens, and not knowing whether or not some scheduled interrupt or other higher priority event would interrupt the execution I took the safe route and set the Loop_counter to 0 upon completion and then checked at the inception to allow a resume in a Non 0 instance. Can I assume by your omission of this operation that I needn't worry about interruption of the code execution?

Also, you may have assumed (since you know I'm an AB guy) that my arrays had a starting element of 0. That is a nice feature of Siemens that I quickly took advantage of, allowing you to vary the starting index, so most of my arrays begin at 1, as there are instances where it is beneficial not to have to offset other operations to allow for a ZERO starting element. With that said, I need to move the first step decrement to a Post Code location. But I wasn't sure if I could simply omit the + -1 at the top and execute two back to back transfers or do I need to perform an inert operation there like + 0 before the second transfer to iArrayIndex? Also I assume I should just jump out at zero, or is there a way to stipulate an alternative loop terminator?

I'm a bit vexed by the structure of the Pointer type. The documentation (help file) shows the DB number located at bytes 0-1, which I know from some of the functions running that array pointers (presumably different in structure) have the DB number located at bytes 4-5, along the same train of thought, I'm unclear on the data area as well. Here's my twisted logic:

To read a single bit in byte 0 no Shift is required, therefore it stands to reason that a Shift left of a single bit would realign the starting location for the read left by 1 full byte, a shift of 2 would result in 2 bytes while a shift of 3 would result in 4 bytes, however I must be wrong, because while a ZERO shift indeed results in a bit read from the first byte of the data area, a shift of 3 is required for a first byte read, so what does one get by shifting 1 or 2 bits left?

Do you by chance have a breakdown of the Array Pointer structure that you could pass along. I have some other functions I've written that I would like to improve but I need a little better understanding of the structure of these pointers.

I am genuinely grateful for all of your assistance and your seemingly endless patience with me.

Regards,

Eric
 
I'll reply to the easy stuff first:

Pointers - there are two types of pointer parameters:

1. A (DB) pointer where bytes 0&1=DB number, bytes 2,3,4,5=Area

2 An Any pointer which can be used for Data Types, timers/counters and blocks. The any pointer for data types is structured as follows
Byte 0 = 16#10
Byte 1 = Type (01=bool 02=byte etc
Byte 2,3 = Number of items of type
Byte 4,5 = DB number
Byte 6,7,8,9 = Area Pointer

I'm using the Any Pointer parameter for the array accesses - again because they were based on a more generalised block. They could be recoded to use the DB pointer type as they do not use the type or number of items from the Any pointer. (Note that the code I posted for the sizeof function does use this information)
Note also that an Any pointer is simply a number of elements of a certain type in an (optional) DB, starting at a particular location. There is nothing to tell that it is actually an array.

Area pointer - here's a link to a previous post. The area pointer specifies down to a bit address so to calculate the byte address you could either multiply by 8 or shift left 3 bits.
http://www.plctalk.net/qanda/showpost.php?p=222839&postcount=6
 
Last edited:
Code interruption - yes the code can be interrupted (by a timed interrupt, for example OB35). But the CPU context is saved and when the timed interrupt is complete the interrupted block will continue. Of course if you use global flags (MW's) or global DB's, then if they are modified by the interrupt routine you may be courting disaster.

You should note that in my recoded example I used a local temp for the loop counter. Your use of a marker word is ok - it's just that the temp area is so convenient for loop counters etc and you don't have to keep track of which marker bits have already been used.

The local temp area is allocated each time a block is called and is only valid whilst the block is executing. The local temp area is de-allocated when the block finishes - hence you cannot use the temp area for storing counts or storing booleans for edge detection.
 
arkansascontrols said:
Also, you may have assumed (since you know I'm an AB guy) that my arrays had a starting element of 0. That is a nice feature of Siemens that I quickly took advantage of, allowing you to vary the starting index, so most of my arrays begin at 1, as there are instances where it is beneficial not to have to offset other operations to allow for a ZERO starting element. With that said, I need to move the first step decrement to a Post Code location. But I wasn't sure if I could simply omit the + -1 at the top and execute two back to back transfers or do I need to perform an inert operation there like + 0 before the second transfer to iArrayIndex? Also I assume I should just jump out at zero, or is there a way to stipulate an alternative loop terminator?
Eric

I'm not sure what you asking here. Are you referring to your original code or my re-coded version ?
 
Your recoded version. It looks like you're initializing the loop variable at 8 but offset the array element index by 1 to account for a 0 starting element. The actual array has a starting element of 1 thus negating the necessity of the offset. My question more specifically is this;

you wrote;

L 8;
RPT: T #iLoopCount; // = 8,7,6,5,4,3,2,1
+ -1;
T #iArrayIndex; // = 7,6,5,4,3,2,1,0

I actually need to start at 8 not at 7 and I need to run through 1 not 0
So can I do 2 Transfers like this;

L 8;
RPT: T #iLoopCount; // = 8,7,6,5,4,3,2,1
T #iArrayIndex; // = 7,6,5,4,3,2,1,0

or should is ACC1 emptied upon the first T. If so I could;

L 8;
RPT: T #iLoopCount; // = 8,7,6,5,4,3,2,1
+ 0;
T #iArrayIndex; // = 7,6,5,4,3,2,1,0

Then at the bottom where you have:

LPCT: L #iLoopCount; //loop counter decrement and test
LOOP RPT;

I could replace with:

LPCT: L #iLoopCount; //loop counter decrement and test
L #iLoopCount;
+ -1;
T #iLoopCount;
LOOP RPT;

Or is there a better way?
 
Last edited:
Last Question of the Night. If I pass an array(with element number) to any ANY Pointer, where is the Passed Element number located within the Pointer Structure?

ie.. DB1.My_Array[16]
Byte 1 = Type of Array
Byte 2,3 = Number of Elements in the Array?
Byte 4,5 = DB1
Byte 6-9 = Value

Wild guess here, but if the Element Number is passed can that be found in Bytes 2,3?
 

Similar Topics

On all pages of my project i have a lot of information, texts and details that should not not be shown. I can remove them for each part apart from...
Replies
0
Views
40
Hi, I have had problem with upgrading some projects from v16 to v18. I tried it on 3 diffrent computers. I want to post this so that anyone that...
Replies
3
Views
165
Hi, I am having a challenge installing a new drive ACS355-03E-44A0-4 as it keeps on displaying Fault code F00018 even when the load is not...
Replies
3
Views
135
I have an issue on my vessel, we have water tight door system created in China, company is no longer operating. We have 7 doors each with their...
Replies
4
Views
143
Hi all. Simple as simple can be, I don't understand what's happening. I'm toggling he OSR on, GX_LUB_PUMP1_LEAD should switch. It doesn't. The...
Replies
27
Views
667
Back
Top Bottom