PDA

Просмотр полной версии : Диммер освещения



toneek
28.09.2017, 14:10
Добрый день. Только начинаю осваивать codesys. Помогите собрать диммер, управляемый одной клавишей. Т.е. пока клавиша нажата, яркость увеличивается от минимального значения до максимального и обратно до минимального.

Осинский Алексей
29.09.2017, 09:45
Вне зависимости от того, программируете Вы на CODESYS, JAVA, C++ и т.д. разработка ПО начнется у Вас с составления алгоритма работы компонента.
Не поленитесь составить алгоритм на листке бумаги или, например, в VISIO.
Так Вы сможете отследить большую часть проблемных мест и поймете что за чем нужно делать при разработке программы.

Предположим Вы составили алгоритм работы диммера и выглядит он как на рисунке ниже:
33364

Нужно сказать, что этот алгоритм я составил для примера и
1) он не идеален. Для использования в реальных проектах нужно как минимум добавить проверку входных величин (например, минимальное значение якрости не должно быть больше максимального, время приращения не должно быть нулевым и т.д).
2) Возможно алгоритм не соответствует Вашим требованиям. Дочитав это сообщение я думаю Вы сможете самостоятельно его доработать под Ваши нужды.

Приступим к программированию.
Многие новички выбирают язык CFC как основной из-за того, что он проще для ознакомления.
Но рекомендую все же привыкать программировать на ST т.к. возможностей здесь больше и реализуется все проще.

Очевидно, что в рамках одного проекта диммеров может быть несколько (для кухни, ванной, зала), поэтому реализовывать алгоритм мы будем как функциональный блок.
Добавляем ФБ в проект и описываем его интерфейс:
33360

и приступаем к реализации алгоритма:
33361

Теперь наш ФБ готов к использованию:
Идем в программу PLC_PRG и пишем:
33362

Загружаем проект в ПЛК, нажимаем кнопку и наслаждаемся тем, как яркость меняется раз в секунду на 1 от 0 до 100 и обратно.

Сам файл проекта можно скачать здесь:

приборист
01.10.2017, 12:17
Ужос и объявление и работа с таймером.
Вот после таких примеров и выкладываются проекты в сотни кб с просьбами посмотреть что не так )))

Может там оплата за строки?

ЗЫ
Больше никак не могу объяснить строки вида:
TON.IN:=false;
TON();

Осинский Алексей
02.10.2017, 08:15
Ужос и объявление и работа с таймером.
Вот после таких примеров и выкладываются проекты в сотни кб с просьбами посмотреть что не так )))

Распишите пожалуйста подробнее в чем я не прав.

Осинский Алексей
02.10.2017, 08:36
Может там оплата за строки?

ЗЫ
Больше никак не могу объяснить строки вида:
TON.IN:=false;
TON();

Объясняется все достаточно просто:
единый стиль написания кода.
И если при необходимости передачи одного параметра выглядит так, как будто, это ЦЕЛАЯ дополнительная строка кода.
То при десятке входных параметров все выглядит гораздо читабельнее, чем вот такая вот конструкция:
33419


Если есть соображения как лучше подходить к оформлению кода - с удовольствием их выслушаю.

Если Вы при разработке ПО пользуетесь каким-либо стандартом оформления кода - поделитесь пожалуйста, возможно мы сможем почерпнуть что-либо для себя.

capzap
02.10.2017, 09:06
Если Вы при разработке ПО пользуетесь каким-либо стандартом оформления кода - поделитесь пожалуйста, возможно мы сможем почерпнуть что-либо для себя.
вот на скрине, много параметров у ПОУ для читабельности разнесены в несколько строк

Осинский Алексей
02.10.2017, 21:34
Причем тут прав/неправ ? Для достижения результата можно и еще килобайт двадцать добавить и тоже будет "прав".
Конкретнее, пожалуйста.
В чем ошибка?



Накой такие длинные названия ?

"Говорящие" названия переменных и типов данных повышают читаемость (и, как следствие, сопровождаемость) кода.
Особенно актуально при разработке в команде.
При именовании переменных я пользуюсь следующими правилами :

Имя переменной должно однозначно указывать ее назначение;
Имя переменной должно содержать префикс области видимости и тип переменной;
Стиль написания имени: UpperCamelCase;
Длина до 20 символов (без учета префиксов).



К стати, это ни коим образом не сказывается ни на размере скомпилированного кода ни на времени выполнения.



Смена знака - шедевр. Особенно с комментом.

Это ведь форум. Мы все помогаем друг другу развиваться.
Предложите Ваш вариант.


Зачем таймер вызывать в 2х местах ?
В трех.
Это действительно недосмотр.

Осинский Алексей
03.10.2017, 06:18
А где я говорил про ошибку ? Я это назвал ужосом. Для начинающего.
Без аргументов этот разговор не имеет смысла.
Здесь важнее мнение toneek. Помогло ли ему и было ли ему все понятно.


Зачем тогда коменты если названия - говорят ?
Пример для начинающего.
1) Очевидно, что чем больше я прокомментирую, тем меньше вопросов возникнет.
2) Комментарии соответствуют надписям на блок схеме. Я думаю Вы не станете спорить, что это упростит понимание для новичка?


Для смены знака ? Надо было делить на -1
Почему же?

Иса
11.04.2019, 21:24
Тебя помогите в написании кода на cfc для освещения. Каждый раз начиная ухожу в дебри. Большой массивная схема получается. Может все же проще сможете к можете. Задача такая. Две кнопки. Одна с фиксацией для вкл/выкл света,вторая без фиксации для диммирования. То есть когда свет включен, долгое нажатие второй кнопки затухает свет, когда свет выключен, долгое нажатие плавно включает свет. Ну и естественно все это сбрасывается при переключение первого выключателя
Ну как вам задачка?

krollcbas
12.04.2019, 01:08
(* @NESTEDCOMMENTS := 'Yes' *)
(* @PATH := '\/EXE' *)
(* @OBJECTFLAGS := '0, 8' *)
(* @SYMFILEFLAGS := '2048' *)
FUNCTION_BLOCK BTN_DIMM
VAR_INPUT
IN:BOOL;
Addr:BYTE;
END_VAR
VAR_OUTPUT
END_VAR
VAR
FB_DALIV2DirectArcPowerControl:FB_DALIV2DirectArcP owerControl;
byPower,byPower_old:BYTE;
State:INT;
bStart:BOOL;
Count:INT;
TON,TON1:TON;
TP:TP;
LAST_VALUE:BYTE:=254;
R_TRIG:R_TRIG;
F_TRIG:F_TRIG;
END_VAR
(* @END_DECLARATION := '0' *)
IF LAST_VALUE>254 THEN LAST_VALUE:=254; END_IF;

IF IN THEN Count:=Count+1; END_IF;
TON(IN:=NOT TON.Q, PT:=T#50ms);
TON1(IN:=NOT TON1.Q, PT:=T#80ms);

R_TRIG(CLK:=IN);
F_TRIG(CLK:=IN);

CASE State OF
0:(*Свет не горит*)
State:=State;
byPower:=0;
IF Count>3 AND Count<30 AND F_TRIG.Q THEN byPower:= LAST_VALUE; Count:=0; State:=2; END_IF;(*Короткий импульс на свет горит*)
IF Count>30 AND IN THEN Count:=0; State:=1; END_IF;(*Длительный импульс на свет разгорается*)

1:(*Свет загорается*)
State:=State;
IF IN AND byPower<= 255 AND TON1.Q THEN
IF byPower<= 254 THEN byPower:=byPower+1; END_IF;
END_IF;

IF NOT IN THEN LAST_VALUE:=byPower; Count:=0; State:=2; END_IF;(*Значит кнопку отпустили*)
IF byPower>= 254 THEN Count:=0; State:=2; END_IF;(*Значит достигли предела*)

2:(*Свет горит*)
State:=State;
IF Count>3 AND Count<100 AND F_TRIG.Q THEN Count:=0; State:=0; END_IF;(*Короткий импульс на отключение*)
(*IF Count>30 AND IN THEN Count:=0; State:=3; END_IF;Длительный импульс*)
IF Count>30 AND IN AND byPower<= 255 THEN Count:=0; State:=3; END_IF; (*Уменьшаем яркость*)
IF Count>100 THEN Count:=0; END_IF;

3:(*Уменьшаем яркость*)
State:=State;
IF Count>30 AND IN AND byPower<= 255 AND TON1.Q THEN
IF byPower>10 THEN byPower:=byPower-1; END_IF;
LAST_VALUE:=byPower;
END_IF;
IF Count>100 THEN Count:=0; END_IF;
IF F_TRIG.Q THEN State:=2; END_IF; (*Свет по прежнему горит*)

END_CASE;

TP(IN:=(byPower_old<>byPower), PT:=T#300ms);
IF TP.Q THEN bStart:=TRUE; ELSE bStart:=FALSE; END_IF;

(*Блок записи на шине DALI*)
FB_DALIV2DirectArcPowerControl(
bStart:= TON.Q,
nAddr:= Addr,
eAddrType:= eDALIV2AddrTypeShort,
eCommandPriority:= eDALIV2CommandPriorityHigh,
nArcPowerLevel:= byPower,
stCommandBuffer:= stComBuf,
bBusy=> ,
bError=> ,
nErrorId=> );

byPower_old:=byPower;(*Отлавливаю изменение уставки*)
END_FUNCTION_BLOCK