Comments 7
Саша, а ты не пробовал сравнивать вышеописанную конструкцию с банальным инкрементом в циклическом ОВ? Да, вызовов больше, но сама вызываемая процедура проще.
Выглядит, как проктологический подход к лечению зубов.
Я так и не понял постановки задачи, какую задачу нельзя решить с использованием стандартных встроенных в систему таймеров?
Ну и общее замечание — не надо использовать REAL без необходимости, он медленный почти на всех подобных железках.
Я так и не понял постановки задачи, какую задачу нельзя решить с использованием стандартных встроенных в систему таймеров?
Ну и общее замечание — не надо использовать REAL без необходимости, он медленный почти на всех подобных железках.
Про подход согласен — натягивание совы на глобус, даже у таймера имя соответствующее задано. Про REAL тоже согласен.
Постановка задачи. Кратко и на пальцах. Выделяем некоторые сущности, например — DI, DO, агрегат. Каждая сущность — это массив элементов, у каждого элемента, соотвественно, есть свой индекс, т.е. уникальный номер. Обработка всех сущностей выполняется в циклах.
Для каждой сущности задается конфигурацию в реманентной памяти.
Для DI
-сигнал не в работе, подавать замещающее значение
-замещающее значение
-сигнал инвертирован
-время фильтрации дребезга контактов
Для DO
-сигнал не в работе, подавать замещающее значение
-замещающее значение
-сигнал инвертирован
-длительность управляющего импульса
Для агрегата
-индексы сигналов состояния
-индексы сигналов управления
-куча другого
У S7-300, особенно у тех, которые были поколение-два назад, все не очень хорошо с рабочей (оперативной) памятью, ее очень мало. По этой причине и заворачивали обработку в циклы. Память экономится значительно, но читаемость такого кода очень низкая.
В «тысячной» серии с рабочей памятью стало гораздо лучше, поэтому описанный в заметке пример носит больше демонстрационный и ностальгический параметр.
Постановка задачи. Кратко и на пальцах. Выделяем некоторые сущности, например — DI, DO, агрегат. Каждая сущность — это массив элементов, у каждого элемента, соотвественно, есть свой индекс, т.е. уникальный номер. Обработка всех сущностей выполняется в циклах.
Для каждой сущности задается конфигурацию в реманентной памяти.
Для DI
-сигнал не в работе, подавать замещающее значение
-замещающее значение
-сигнал инвертирован
-время фильтрации дребезга контактов
Для DO
-сигнал не в работе, подавать замещающее значение
-замещающее значение
-сигнал инвертирован
-длительность управляющего импульса
Для агрегата
-индексы сигналов состояния
-индексы сигналов управления
-куча другого
У S7-300, особенно у тех, которые были поколение-два назад, все не очень хорошо с рабочей (оперативной) памятью, ее очень мало. По этой причине и заворачивали обработку в циклы. Память экономится значительно, но читаемость такого кода очень низкая.
В «тысячной» серии с рабочей памятью стало гораздо лучше, поэтому описанный в заметке пример носит больше демонстрационный и ностальгический параметр.
Для подобных целей сначала использовал самописную функцию
Теперь использую стандартные таймеры.
FC_On_Delay
FUNCTION "FC_On_Delay" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
input : Bool;
current_time : Time;
interval : Time;
END_VAR
VAR_IN_OUT
prev_input : Bool;
output : Bool;
start_time : Time;
END_VAR
BEGIN
IF #output <> #input THEN
IF #input THEN
IF #prev_input THEN
IF (#current_time - #start_time) > #interval THEN
#output := true;
END_IF;
ELSE
#start_time := #current_time;
END_IF;
ELSE
#output := false;
END_IF;
END_IF;
#prev_input := #input;
END_FUNCTION
Теперь использую стандартные таймеры.
Тестовый пример
TYPE "test_timer_t"
VERSION : 0.1
STRUCT
"timer" {InstructionName := 'IEC_TIMER'; LibVersion := '1.0'} : IEC_TIMER;
in : Bool;
pt : Time := T#10S;
q : Bool;
et : Time;
END_STRUCT;
END_TYPE
TYPE "test_ton_timer_t"
VERSION : 0.1
STRUCT
"timer" {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;
in : Bool;
pt : Time := T#10S;
q : Bool;
et : Time;
END_STRUCT;
END_TYPE
TYPE "test_tof_timer_t"
VERSION : 0.1
STRUCT
"timer" {InstructionName := 'TOF_TIME'; LibVersion := '1.0'} : TOF_TIME;
in : Bool := true;
pt : Time := T#10S;
q : Bool;
et : Time;
END_STRUCT;
END_TYPE
DATA_BLOCK "DB_timers"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
VAR
timers : Array[1..100] of "test_timer_t";
ton_timers : Array[1..100] of "test_ton_timer_t";
tof_timers : Array[1..100] of "test_tof_timer_t";
END_VAR
BEGIN
END_DATA_BLOCK
FUNCTION "FC_test_timers" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
i : Int;
END_VAR
BEGIN
FOR #i := 1 TO 100 DO
"DB_timers".timers[#i].timer.TON(IN := "DB_timers".timers[#i].in,
PT := "DB_timers".timers[#i].pt,
Q => "DB_timers".timers[#i].q,
ET => "DB_timers".timers[#i].et);
"DB_timers".ton_timers[#i].timer(IN := "DB_timers".ton_timers[#i].in,
PT := "DB_timers".ton_timers[#i].pt,
Q => "DB_timers".ton_timers[#i].q,
ET => "DB_timers".ton_timers[#i].et);
"DB_timers".tof_timers[#i].timer(IN := "DB_timers".tof_timers[#i].in,
PT := "DB_timers".tof_timers[#i].pt,
Q => "DB_timers".tof_timers[#i].q,
ET => "DB_timers".tof_timers[#i].et);
END_FOR;
END_FUNCTION
Sign up to leave a comment.
Самописный таймер в виде функции для промышленного контроллера Simatic S7-1200