Аналог счетчика CTU большой разрядности в CoDeSys v2.

Создание аналога счетчика CTU с максимальным значением DWORD в CoDeSys v2.

При создании программы ПЛК в среде программирования CoDeSys v2 часто используется компонент счетчик CTU. Например, при работе с энкодером он посчитывает импульсы, поступающие с быстрого входа контроллера на вход CU. Выход CV счетчика CTU имеет тип WORD. Что ограничивает его выходное значение максимум 65535-мя подсчитываемыми импульсами (реально он останавливает счет на значении 32767 – максимальном 16 битном числе со знаком). Проблему можно решить, написав собственный счетчик.

Для этого создаем новый функциональный блок. Открываем вкладку PUI, добавляем новый объект.

Открываем вкладку  PUI, добавляем новый объект.

В открывшемся окне выбираем тип PUI - функциональный блок, язык программирования - ST. Даем ему название, например mycounter. Нажимаем кнопку OK.

Выбираем тип PUI.

В открывшемся окне редактора кода задаем следующие переменные

Входные переменные:

inenc: BOOL := FALSE; (*Вход счетчика*)
resetcount: BOOL := FALSE; (*Сброс счетчика*)

Выходные переменные:

countout: DWORD; (*Выход счетчика*)

Задаем выходной переменной тип DWORD что позволит накапливать в нем значения до 4294967295.

Кроме того используем элементы:

R_TRIG – детектор переднего фронта,
и
S_TRIG – детектор заднего фронта.

Подробнее об этих элементах можно прочитать во встроенной справочной системе CoDeSys v2.

Объявляем их в разделе внутренних переменных:

RTRIGInst : R_TRIG ;(*детектор переднего фронта*)
FTRIGInst : F_TRIG ; (*детектор заднего фронта*)

Их задача ловить начало и конец импульса приходящих от энкодера.

Задаем для них две переменные

enin1: BOOL := FALSE; (*Выход детектора переднего фронта*)
enin2: BOOL := FALSE; (*Выход детектора заднего фронта*)

которые будут принимать значение TRYE при прохождении соответствующего фронта импульса.

И промежуточную переменную flag, которая используется для корректной работы счетчика.

flag: BOOL := FALSE; (*Промежуточная переменная*)

В разделе кода пишем:

RTRIGInst(CLK:= inenc);
enin1 := RTRIGInst.Q;

FTRIGInst(CLK:= inenc);
enin2 := FTRIGInst.Q;

IF enin1 = TRUE AND flag = FALSE THEN
countout:=countout+1;
flag:=TRUE;
END_IF;

IF enin2 = TRUE THEN
flag:=FALSE;
END_IF;

IF resetcount = TRUE THEN
countout:=0;
END_IF;

Функциональный блок счетчика.

Далее сохраняем проект, Компилируем, и получаем собственный счетчик, который можем использовать в проекте.

Полный исходный код функционального блока с комментариями:

FUNCTION_BLOCK mycounter

(*Раздел объявления переменных*)

VAR_INPUT inenc: BOOL := FALSE; (*Вход от энкодера*)
resetcount: BOOL := FALSE; (*Сброс счетчика*)
END_VAR

VAR_OUTPUT
countout: DWORD; (*Выходной счетчик*)
END_VAR

VAR
flag: BOOL := FALSE; (*Флаг что пришел передний фронт*)
RTRIGInst : R_TRIG ;(*детектор переднего фронта*)
FTRIGInst : F_TRIG ; (*детектор заднего фронта*)
enin1: BOOL := FALSE; (*Выход детектор переднего фронта*)
enin2: BOOL := FALSE; (*Выход детектор заднего фронта*)
END_VAR

(*Раздел кода*)

RTRIGInst(CLK:= inenc);
enin1 := RTRIGInst.Q; FTRIGInst(CLK:= inenc);
enin2 := FTRIGInst.Q; IF enin1 = TRUE AND flag = FALSE THEN
countout:=countout+1;
flag:=TRUE;
END_IF;
IF enin2 = TRUE THEN
flag:=FALSE;
END_IF;
IF resetcount = TRUE THEN
countout:=0;
END_IF;

О том как использовать этот функциональный блок в программе CoDeSys можно прочитать в следующем разделе.