Page 1 of 1

Вызов функционального блока с индексированным вызовом экземп

Posted: Mon Jul 02, 2012 3:37 am
by Balagur
Доброго времени суток!

Для написания программ нижнего уровня использую S7-SCL V5.3.5.1 из программного пакета Step7 V5.5.

Интересует вопрос: возможен ли вызов функционального блока с индексированным вызовом экземплярного блока данных, согласно задаче.

Например:
- есть функциональный блок FB1
- есть созданные для него экземплярные базы данных DB1-DB9
- в OB1 (не принципиально, можно использовать еще один функциональный блок с вызовом FB1 например, для хранения локальных переменных и т.д.) должны вызываться последовательно FB1.DB1 (); ... FB1.DB9 ();.

Так вот, возможно ли реализовать вызов функционального блока (по сути, идентичной программы для 9-ти разных объектов) с разными экземплярными блоками с использованием, например, оператора FOR? Например, так:

For i=1 to 9 do
FB1.DB [индекс_базы_данных] (параметры блока);
End_For;

Ясно, что написан пример неправильно.

Re: Вызов функционального блока с индексированным вызовом эк

Posted: Mon Jul 02, 2012 10:18 am
by bilbo_321
Hi Balagur,

You can't call FB with index of instance DB as I know.
You can try to define UDT with structure of your DB and then create a DB with array of that UDT.
later in OB1 or FC you can call your FB in a cycle with I/O variable of the same UDT type.
See the code below.
code
Show

Code: Select all

//=================== TYPE DECLARATION ========================
TYPE UDT1
    STRUCT
    // Sample UDT
    SAMPLE_INT1:INT;
    SAMPLE_INT2:INT;
    SAMPLE_INT3:INT;
    END_STRUCT
END_TYPE
//============================================================

//=================== DATA BLOCK FOR ALL 10 ITEMS ============
DATA_BLOCK DB1
//
// Block Comment ...
//
    STRUCT
       DEVICES:ARRAY[1 .. 10] OF UDT1;
    END_STRUCT
BEGIN

END_DATA_BLOCK
//============================================================

//=================== CONTROL FB =============================
FUNCTION_BLOCK FB1

VAR_IN_OUT
    // I/O Parameters
    DEVICE:UDT1;
END_VAR
    // Statement Section
    DEVICE.SAMPLE_INT2 := DEVICE.SAMPLE_INT1;
END_FUNCTION_BLOCK
//============================================================

//=================== OB1 ====================================
ORGANIZATION_BLOCK OB1

VAR_TEMP
    // Reserved
    info : ARRAY[0..19] OF BYTE;
    Index:INT;
    // Temporary Variables
END_VAR
    
    FOR Index:= 1 TO 10 DO
        // Statement Section
        FB1.DB10(DEVICE :=  DB1.DEVICES[Index]);
        ;
    END_FOR;  

END_ORGANIZATION_BLOCK
//============================================================

Actually you can use FC instead of FB. It is your choice.
Hope this is helpful.

Re: Вызов функционального блока с индексированным вызовом эк

Posted: Tue Jul 03, 2012 3:51 pm
by Balagur
bilbo_321, добрый день!

Спасибо за пример!

Однако, я не договорил условия задачи.
1. Часть переменных должны с экземплярных баз данных DB1-DB9 передаваться соответственно в глобальные базы данных DB100-DB900 для вывода на верхний уровень для 9-ти разных объектов.
2. Другая часть переменных экземплярных баз данных, должна обрабатываться как локальные переменные (раздел деклараций VAR...END_VAR), индивидуальные для каждого объекта.

Так вот, я последовал Вашему примеру, и объединил переменные экземплярных баз данных DB1-DB9 в одну экземплярную базу DB1. Доступ к локальным переменным этой базы для разных объектов достигается использованием массива с индексацией 1-9.

Тажке, я реализовал алгоритм передачи параметров (в OB1) в глобальные базы данных DB100-DB900, используя функцию "WORD_TO_BLOCK_DB". Однако, в данном случае, приходится вручную присваивать параметр блока к области глобальной базы данных (DB100-DB900).
code
Show

Code: Select all

//=================== TYPE DECLARATION ========================
TYPE UDT0
    STRUCT
    // Sample UDT
    WORD_0      :   WORD;
    WORD_1      :   WORD;
    WORD_2      :   WORD;
    END_STRUCT
END_TYPE
//============================================================

//=================== GLOBAL DATA BLOCK  =================
DATA_BLOCK DB100
    UDT0;
BEGIN
END_DATA_BLOCK
DATA_BLOCK DB200
    UDT0;
BEGIN
END_DATA_BLOCK
//.......
DATA_BLOCK DB900
    UDT0;
BEGIN
END_DATA_BLOCK
//============================================================

//=================== CONTROL FB =============================
FUNCTION_BLOCK FB1

VAR_IN_OUT
    // I/O Parameters
    word_0      :   WORD;
    word_1      :   WORD;
    word_2      :   WORD;
    
    index       :   INT;    
END_VAR

VAR
    //block memory
    step    :   ARRAY [1..9] OF BOOL;
END_VAR

    // Statement Section
    word_0  :=  word_1;
    step [index]    :=  0;
END_FUNCTION_BLOCK
//============================================================

//=================== OB1 ====================================
ORGANIZATION_BLOCK OB1

VAR_TEMP
    // Reserved
    info : ARRAY[0..19] OF BYTE;
    Index:INT;
    // Temporary Variables
    word_0  :   WORD;
    word_1  :   WORD;
    word_2  :   WORD;
END_VAR
    
    FOR Index:= 1 TO 9 DO
        // входные преобразования
        word_0  :=  WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW0;
        word_1  :=  WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW2;
        word_2  :=  WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW4;
        // Statement Section
        FB1.DB1 (
                    index   :=  index,
                    word_0  :=  word_0,
                    word_1  :=  word_1,
                    word_2  :=  word_2
                );
        //выходные преобразования
        WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW0 :=  word_0;
        WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW2 :=  word_1;
        WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW4 :=  word_2;
    END_FOR;  

END_ORGANIZATION_BLOCK
//============================================================

bilbo_321, подскажите, может быть можно реализовать задачу в OB1 более рациональным способом?

Re: Вызов функционального блока с индексированным вызовом эк

Posted: Thu Jul 05, 2012 10:53 am
by bilbo_321
You could put
"// входные преобразования
word_0 := WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW0;
word_1 := WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW2;
word_2 := WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW4;
"
and
"//выходные преобразования
WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW0 := word_0;
WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW2 := word_1;
WORD_TO_BLOCK_DB (INT_TO_WORD (index*100)).DBW4 := word_2;
"
into FB1 and transfer only one input parameter "index" to FB1.

I don't think it is better because your code will be less readable.
It is good practice to avoid direct or indirect addressing to external DBs or memory inside the FB or FC. It is better to transfer external data through I/O parameters of FB or FC and your code is tidy and easy to understand.

Good luck!