PS Используется программный PLC
PS Используется программный PLC
формированием маски массива, то, что "1" принимаем в работу, что "0" не принимаем.
Не знаю, как это на ST описать, на C# примерно такое делал, там где проставлял true, уходило в работу, остальное отбрасывалось.
У меня было два массива в результате. в Первом "источник" (например кран 1, кран 10, кран 23 и т.д.) во втором их данные.
Предположим у Вас есть ФБ ValveController, который осуществляет управление задвижкой.
ФБ выглядит примерно так:
Там, где Вам необходимо объявите массив ФБ (для примера объявлю в глобальных переменных):Код:FUNCTION_BLOCK ValveController VAR_INPUT sNameToSet : STRING; END_VAR VAR_OUTPUT sName : STRING; END_VAR VAR END_VAR // Тело ФБ: IF (sName = '') AND (sNameToSet <> '') THEN sName := sNameToSet; END_IF
и проинициализируйте его например так:Код:VAR_GLOBAL CONSTANT g_c_uiValvesCount : UINT := 30; END_VAR VAR_GLOBAL g_astValvesList : ARRAY [1..g_c_uiValvesCount] OF ValveController; i : UINT; END_VAR
Код:IF NOT m_xIsValvesInitialized THEN FOR i := 1 TO g_c_uiValvesCount DO g_astValvesList[i].sNameToSet := UINT_TO_STRING (i); g_astValvesList[i](); END_FOR m_xIsValvesInitialized := TRUE; END_IF
Когда станет известно к какой задвижке обратиться Вам нужно будет всего лишь найти индекс задвижки в массиве зная ее имя.
Например так:
Когда нужно будет обратиться к задвижке выполните кодКод:(* Функция возвращает индекс задвижки в массиве по ее имени. Если задвижка с указанным именем не найдена - вернет 0 *) FUNCTION FindValveIndexByName : UINT VAR_INPUT sValveToFindName : STRING; END_VAR VAR i : UINT; END_VAR // Тело функции FindValveIndexByName := 0; i := 1; WHILE (FindValveIndexByName = 0) AND (i <= g_c_uiValvesCount) DO IF g_astValvesList[i].sName = sValveToFindName THEN FindValveIndexByName := i; END_IF i := i + 1; END_WHILE
Единственное что нужно помнить - перебор 30000 значений приведет к увеличению времени цикла.Код:uiCurrentValveIndex := FindValveIndexByName ('5'); IF uiCurrentValveIndex > 0 THEN (* Тут выполняете необходимые манипуляции с задвижкой примерно так g_astValvesList[uiCurrentValveIndex].state *) END_IF
Поэтому выполняйте поиск по имени только тогда, когда это действительно важно.
В приложении файл, содержащий код из этого сообщения.
Последний раз редактировалось Осинский Алексей; 28.02.2018 в 12:26.
OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС
Если же Вы хотите сохранить возможность работы с задвижкой по имени переменной в программе подойдет второй способ:
Допустим ФБ Вашей задвижки выглядит так:
Объявите структуруКод:FUNCTION_BLOCK ValveController VAR_INPUT END_VAR VAR_OUTPUT dwState : DWORD; END_VAR VAR END_VAR
Объявите массив структур (для примера в глобальных переменных)Код:TYPE NAMED_VALVE : STRUCT sName : STRING; pfbValve : POINTER TO ValveController; END_STRUCT END_TYPE
Инициализируйте массив например так:Код:VAR_GLOBAL CONSTANT g_c_uiValvesCount : UINT := 30; END_VAR VAR_GLOBAL g_astValvesList : ARRAY [1..g_c_uiValvesCount] OF NAMED_VALVE; END_VAR
Когда станет известно к какой задвижке обратиться Вам нужно будет всего лишь найти индекс задвижки в массиве зная ее имя.Код:IF NOT m_xIsValvesInitialized THEN FOR i := 1 TO g_c_uiValvesCount DO g_astValvesList[i].sName := UINT_TO_STRING (i); g_astValvesList[i].pfbValve := 0; (* Вместо 0 ADR (экземпляр ФБ задвижки) *) END_FOR m_xIsValvesInitialized := TRUE; END_IF
Например так:
Чтобы обратиться к задвижке выполните кодКод:(* Функция возвращает индекс задвижки в массиве по ее имени. Если задвижка с указанным именем не найдена - вернет 0 *) FUNCTION FindValveIndexByName : UINT VAR_INPUT sValveToFindName : STRING; END_VAR VAR i : UINT; END_VAR // Тело функции FindValveIndexByName := 0; i := 1; WHILE (FindValveIndexByName = 0) AND (i <= g_c_uiValvesCount) DO IF g_astValvesList[i].sName = sValveToFindName THEN FindValveIndexByName := i; END_IF i := i + 1; END_WHILE
Код:uiCurrentValveIndex := FindValveIndexByName ('5'); IF uiCurrentValveIndex > 0 THEN IF g_astValvesList[i].pfbValve <> 0 THEN ;(* Тут выполняете необходимые манипуляции с задвижкой примерно так g_astValvesList[i].pfbValve^.dwState*) END_IF END_IF
OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС
Э-э, я дико извеняюсь, но объясните, пожалуйста, в чем смысл такой конструкции
Не проще ли тупо написать g_astValvesList : ARRAY [1..g_c_uiValvesCount] OF STRINGКод:
FUNCTION_BLOCK ValveController
VAR_INPUT
sNameToSet : STRING;
END_VAR
VAR_OUTPUT
sName : STRING;
END_VAR
VAR
END_VAR
// Тело ФБ:
IF (sName = '') AND (sNameToSet <> '') THEN
sName := sNameToSet;
END_IF
Там, где Вам необходимо объявите массив ФБ (для примера объявлю в глобальных переменных):
Код:
VAR_GLOBAL CONSTANT
g_c_uiValvesCount : UINT := 30;
END_VAR
VAR_GLOBAL
g_astValvesList : ARRAY [1..g_c_uiValvesCount] OF ValveController;
i : UINT;
END_VAR
Написать-то можно. А как потом понять что за задвижка под этим именем понимается?
Варианта 2:
1) Задвижка сама знает своем имя и входит в общий список задвижек (решение, приведенное в посте 13);
2) Задвижки не знают своих имен, но где-то в системе есть список всех задвижек с именами и указателями на них (решение, приведенное в посте 14).
Последний раз редактировалось Осинский Алексей; 28.02.2018 в 16:10.
OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС