Заглянуть надо. Посмотреть параметр "Безопасное состояние". Вдруг пригодится.
Вид для печати
Добрый день! Подскажите, пожалуйста, как в Codesys можно проверить переменная увеличивается или уменьшается?
делаете генератор импульсов, например через каждые 5 секунд. Когда пришел импульс смотрим, если текущая температура больше предыдущей, то значит температура повышается, если меньше, то понижается. Далее сохраняем текущую температуру, через 5 секунд она нам понадобится как предыдущая для дальнейшего анализа.
Во как все запутано:)
Вспоминаем мат.анализ. В частности поиск интервалов возрастания, убывания и точек экстремума функций с помощью производных.
Как гласит мат.анализ
– если первая производная на интервале больше 0, то функция возрастает на данном интервале;
– если первая производная на интервале меньше 0, то функция убывает на данном интервале.
Нахождение точек максимума и минимума опустим.
Таким образом для решения задачи можно использовать ФБ DERIVATIVE (численное дифференцирование) из стандартной библиотеки Util.
На вход подаем анализируемую переменную. Если на выходе имеем значение >0, то переменная возрастает, если <0, то переменная уменьшается, если =0, то переменная не изменяется во времени.
Удачи:rolleyes:
Попался экземпляр стандарта IEC61131-3 за 2003 год. Офигеть: оказывается, после END_IF, END_CASE, END_FOR и т.п. должна ставиться точка с запятой.Код:IF a THEN
b();
END_IF;
Во все алгоритмических языках операторы заканчиваются ;
Вложение 14236Вложение 14237Вложение 14238Вложение 14239
Кино делать не умею, поэтому выкладываю картинки в порядке очерёдности. Вопрос, почему два одинаковых триггера работают по разному? Почему триггер DD3 не сбрасывается в исходное состояние?
IEC 61131-3:Кодесису пофиг.Цитата:
Multiple leading or multiple embedded underlines are not allowed; for example, the character sequences __LIM_SW5 and LIM__SW5 are not valid identifiers. Trailing underlines are not allowed; for example, the character sequence LIM_SW5_is not a valid identifier.
i: INT;
i.FALSE := i.TRUE;
Ржака.
arr: ARRAY[1..-1] OF INT;
Error 3801: The variable 'arr' is too large (-2 bytes).
Ржака.
arr2: ARRAY [0..-1] OF INT;
0 Error(s), 0 Warning(s)
Уохахаха
Цитата:
Сообщение от IEC 61131-3
0 Error(s), 0 Warning(s)Код:arr: ARRAY [0..2] OF INT := 1, 2, 3;
Error 3760L PLC_PRG (4): Erroneous initial valueКод:arr: ARRAY [0..2] OF INT := [1, 2, 3];
codesys, please
0 Error(s), 0 Warning(s)Код:VAR CONSTANT RETAIN
http://i.imgur.com/JqaeAQa.png
А функциональные блоки являются типом данных или нет? Не вижу нигде ссылки на это в стандарте, но почему-то кодесис проглатывает это:Код:TYPE subtype : TON := (PT := T#3s); END_TYPE
Мы же можем объявить переменную типа TON. А это и есть функциональный блок.
У меня вопрос больше теоретический. С одной стороны, в стандарте в определении типа никак не упоминаются функциональные блоки. С другой, инстанциируются они как переменные структурного типа (опять же по стандарту). Если кто-то ещё стандарт точит — особенно третью его версию, которую я не могу себе позволить — то поделитесь своим мнением.
Конечно, я тут сам прибегаю к эмпирическому методу — смотрю, как ведёт себя кодесис. Но с учётом вот этих глупых расхождений, которые я показал в предыдущих сообщениях, доверия к нему у меня нет.
Кто с другими средами работает? Напишите, можно ли там тип от функционального блока объявлять как в сообщении 337. Спасибо.
А вот это уже не смешно (d1: DATE):
Вложение 16141
а попробуйте преобразовать один тип в другой через _TO_ ,компилятор будет ругаться, так почему же он должен корректно производить арифметические действия с несовместимыми типами?
ЗЫЦитата:
d1:=DATE#2015-01-13 - T#1h;
d2:=DATE_TO_DWORD(DATE#2015-01-13);
d3:=TIME_TO_DWORD(T#1h);
d4:=DWORD_TO_DATE(d2-d3);
Это уже будет обход бага. Мы проверяем неявное, а не явное приведение типов.Цитата:
а попробуйте
Он должен вываливаться с ошибкой типизации примерно вот так:Цитата:
почему же он должен корректно производить арифметические действия с несовместимыми типами?
Вложение 16143
Зависимость результата от порядка слагаемых в таком случае говорит о приведении по левому операнду. Значит, должно происходить неявное приведение правого операнда к совместимому налево типу, но этого явно не происходит. Это примерно как reinterpret_cast когда должно быть static_cast (C++). Представьте, что пытаясь сложить REAL#3.42 и DINT#5 в DINT вы получаете DINT#12000334 вместо ошибки (если сильная типизация) или DINT#8 с предупреждением о потере точности (если слабая типизация). Но именно такая хрень типа DINT#12000334 получается с комбинацией "DATE слева TIME справа". И по всем признакам (вроде необходимости делать REAL_TO_DINT) языки IEC61131 должны быть сильно типизированными.
Даже ещё проще. Если возможно неявное приведение TIME к DATE в качестве одного из арифметических операндов, то должно быть возможно и приведение в качестве правого операнда присваивания, но ведь его нет:
Вложение 16145
Тупо баг компилятора, причём в третьей версии то же самое.
Цитата:
нет там никакого приведения
Не будь приведения, была бы ошибка (см. скриншот 1 в посте №342).Цитата:Типы у процессора свои (32-разрядное целое — один из них).Цитата:
арифмитическая операция в процессоре идет не типами данных,а 32-разрядными словами
Не важно как и не важно ложная ли. Попытка сложить DATE и TIME с целью получить DATE должна считаться ошибкой в любом случае примерно как попытка сложить DINT и REAL в DINT (оба этих типа тоже можно интерпретировать как 32-разрядные целочисленные — см. на скриншоте как я заставляю это делать компилятор C++). У кодесиса факап ещё на этапе семантического анализа в части типобезопасности, а не на этапе кодогенерации или исполнения.Цитата:
код я привел как получается ложная дата
Картина маслом: симулятор смотрит на компилятор с недоумением и молчит
Вложение 16154
ошибка потому что из меньшего вычитается большее значения, компилятор начинает проверять можно ли такое находит что типы не совместимы и выыдает ругательство, а компилятор кодесисовский и какой то другой, да под разные процессоры совершенно разные, уж если на то пошло сравните как обращается с типами тот же Си и яваскрипт
Подскажите как в CoDeSys привязать визуализацию процесса к программе? Например, должно происходить наполнение бака жидкостью до определенного момента, после чего начинается опорожнение.
Алгоритм описывается в программе. И только в программе.
А визуализация привязывается просто к значениям переменной. В визуализации добавляете бар, и указываете в нем переменную, отвечающую за уровень бака. И БАР будет просто отображать значение этой переменной.
на ютубе видел примеры работы с барами по визуализации вот у этого человека в частности http://www.youtube.com/user/nhfdybr/videos
подскажите пожалуйста нормальные методы загонять bit в word и нооборот
вот тут я выложил пример http://www.owen.ru/forum/showthread....l=1#post172551 не уверен что действую правильно
Как избавиться от зюзь в комментариях , т.е. русифицировать ее под Win7?
Проект -> Опции -> Редактор -> Шрифт -> выбрать "Arial" -> в Анимация с "Западноевропейский" переключить на "Кириллица" -> нажать "ОК"Цитата:
Как избавиться от зюзь в комментариях , т.е. русифицировать ее под Win7?
Вложение 19766
Вложение 19767
Вложение 19768
WTF?
Вложение 19942
Добрый день!
Установщик библиотек (http://www.owen.ru/uploads/txtlic.ph.../Lib_setup.exe)
с вирусом "Trojan.Filecoder.W"
Симулятор игнорирует NaNы!!! Стыд, позор, ппц.
ПЛК160:Код:PROGRAM PLC_PRG
VAR
bin: UDINT := 2#0111_1111_1000_0000_0000_0000_0000_0001;
nan: POINTER TO REAL;
equ: BOOL;
END_VAR
nan := ADR(bin);
equ := nan^ = nan^;
Вложение 21021
Симулятор:
Вложение 21022
Бонус:
Вложение 21023
А ещё нет способа задать NaN напрямую и 0.0 / 0.0 не компилируется.
UPD! Ой мама дорогая... Держите меня семеро:
Вложение 21024 Вложение 21025
Похоже, моим мечтам о NaN'ах в Кодесисе не суждено сбыться. По крайней мере тестировать код не получится.
Ыыы. Зато в докуменитации описаны функции приведения к дате булевских типов:
"BOOL_TO Conversions
Conversion from type BOOL to any other type:
.......
t:=BOOL_TO_TIME(TRUE);
(* Result is T#1ms *)
tof:=BOOL_TO_TOD(TRUE);
(* Result is TOD#00:00:00.001 *)
dat:=BOOL_TO_DATE(FALSE);
(* Result is D#1970 *)
dandt:=BOOL_TO_DT(TRUE);
(* Result is DT#1970-01-01-00:00:01 *)"
Имеется рабочая программа для погодного регулирования с точностью 0,5 градуса. Но когда контроллер поддерживает целое значение температуры теплоносителя, например 50 гр., то точность становится 1 гр.: от 49,5 до 50,5 гр. Если поддерживается, например 50,5 гр. о точность становится 0,5 гр.: от 50,25 до 50,75 гр.
Где нужно подкорректировать программу чтобы точность поддержания температуры была 0,5 гр.?
PROGRAM PLC_PRG
VAR
ind_temp: INT;
ton1,ton2: TON;
df: DECODE_FLOAT;
ust_temp: REAL;
temp_pod_i: INT;
first_start: BOOL := TRUE;
(*old_mode: INT;
old_pod_ust: INT;
old_ust_temp_z: INT;*)
temp_pod, ust_temp_f: REAL;
temp_nv: REAL;
delta: REAL;
ind_temp1: REAL;
END_VAR
VAR RETAIN
temp: ARRAY [0..78] OF REAL;
(*mode_r: INT;
pod_ust_r: INT;
ust_temp_r: INT;*)
NaprReg_r:REAL;
END_VAR
…………………………………………………………………………………………………………………………………… …………………………….
NaprReg := NaprReg_r;
IF first_start THEN
(* +8 +7.5 +7 +6.5 +6 *)
temp[0] := 35; temp[1] := 36; temp[2] := 36; temp[3] := 36; temp[4] := 36;
(* +5.5 +5 +4.5 +4 +3.5 *)
temp[5] := 36; temp[6] := 36; temp[7] := 36; temp[8] := 36; temp[9] := 36.5;
(* +3 +2.5 +2 +1.5 +1 *)
temp[10] := 37; temp[11] := 37.5; temp[12] := 38; temp[13] := 38.5; temp[14] := 39;
(* +0.5 0 -0.5 -1 -1.5 *)
temp[15] := 39.5; temp[16] := 40; temp[17] := 40.5; temp[18] := 41; temp[19] := 41.5;
(* -2 -2.5 -3 -3.5 -4 *)
temp[20] := 42; temp[21] := 42.5; temp[22] := 43; temp[23] := 43.5; temp[24] := 44;
(* -4.5 -5 -5.5 -6 -6.5 *)
temp[25] := 44.5; temp[26] := 45; temp[27] := 45.5; temp[28] := 46; temp[29] := 46.5;
(* -7 -7.5 -8 -8.5 -9 *)
temp[30] := 47; temp[31] := 47.5; temp[32] := 48; temp[33] := 48.5; temp[34] := 49;
(* -9.5 -10 -10.5 -11 -11.5 *)
temp[35] := 49; temp[36] := 49; temp[37] := 49.5; temp[38] := 50; temp[39] := 50;
(* -12 -12.5 -13 -13.5 -14 *)
temp[40] := 50; temp[41] := 50.5; temp[42] := 51; temp[43] := 51; temp[44] := 51;
(* -14.5 -15 -15.5 -16 -16.5 *)
temp[45] := 51.5; temp[46] := 52; temp[47] := 52.5; temp[48] := 53; temp[49] := 53.5;
(* -17 -17.5 -18 -18.5 -19 *)
temp[50] := 54; temp[51] := 54.5; temp[52] := 55; temp[53] := 55.5; temp[54] := 56;
(* -19.5 -20 -20.5 -21 -21.5 *)
temp[55] := 56.5; temp[56] := 57; temp[57] := 57.5; temp[58] := 58; temp[59] := 58.5;
(* -22 -22.5 -23 -23.5 -24 *)
temp[60] := 59; temp[61] := 59.5; temp[62] := 60; temp[63] := 60.5; temp[64] := 61;
(* -24.5 -25 -25.5 -26 -26.5 *)
temp[65] := 61.5; temp[66] := 62; temp[67] := 62.5; temp[68] := 63; temp[69] := 63.5;
(* -27 -27.5 -28 -28.5 -29 *)
temp[70] := 64; temp[71] := 64.5; temp[72] := 65; temp[73] := 65.5; temp[74] := 66;
(* -29.5 -30 -30.5 -31 *)
temp[75] := 66.5; temp[76] := 67; temp[77] := 67.5; temp[78] := 68;
IF NaprReg=0.0 THEN
NaprReg := 0.5;
END_IF;
first_start := FALSE;
END_IF;
df( VALUE:=temp_pod_d, DEF_VALUE:= temp_pod);
CASE df._ERR OF
12: temp_pod_s := 2000; (* кз *)
13: temp_pod_s := 2001; (*обрыв *)
6,7,8,9,10,11,14,15: temp_pod_s := 2002; (*ошибка контроллера *)
ELSE
temp_pod_s := REAL_TO_INT(df.OUT_VALUE*10);
temp_pod := temp_pod_d;
END_CASE;
df( VALUE:=temp_nv_d, DEF_VALUE:=temp_nv);
CASE df._ERR OF
12: temp_nv_s := 2000; (* кз *)
13: temp_nv_s := 2001; (*обрыв *)
6,7,8,9,10,11,14,15: temp_nv_s := 2002; (*ошибка контроллера *)
ELSE
temp_nv_s := REAL_TO_INT((df.OUT_VALUE+50.0)*10);
temp_nv := temp_nv_d;
END_CASE;
ind_temp1 := temp_nv;
ind_temp := 16 - REAL_TO_INT(ind_temp1*2);
IF ind_temp < 0 THEN
ind_temp := 0;
ELSIF ind_temp > 78 THEN
ind_temp := 78;
END_IF;
IF mode = 1 THEN
ust_temp := temp[ind_temp]+pod_ust;
ELSE
ust_temp := ust_temp_z;
END_IF;
temp_pod_i := REAL_TO_INT(temp_pod);
ust_temp_f := (ust_temp);
ton1.PT := t#10m; ton2.PT := t#10s;
ton1(in :=TRUE); ton2(in :=TRUE);
IF ton1.ET >t#30s THEN
IF (temp_pod_i >ust_temp) AND (temp_pod_s <2000) AND ((temp_nv_s<2000) OR (mode=0)) THEN
delta :=(temp_pod - ust_temp_f)/500;
NaprReg := NaprReg +delta;
IF NaprReg > 0.90 THEN NaprReg := 0.90; END_IF;
END_IF;
IF (temp_pod_i delta :=(ust_temp_f - temp_pod)/500 ;
NaprReg := NaprReg -delta;
IF NaprReg < 0.0 THEN NaprReg := 0.0; END_IF;
END_IF;
ton1(in :=FALSE);
END_IF;
NaprReg_r := NaprReg;
napr_s :=REAL_TO_INT( NaprReg *1000);
IF ton2.ET >t#400ms THEN
ton2(in :=FALSE);
ClearScreen(0);
SetWorkScreen(0);
ShowString(0,0,0,'Тнв=');
CASE temp_nv_s OF
2000: ShowString(0,4,0,'КЗ ');
2001: ShowString(0,4,0,'Обр ');
2002: ShowString(0,4,0,'Ош. ');
ELSE
ShowReal(0, 4, 0, '%3.1f',temp_nv);
END_CASE;
ShowString(0,9,0,'Тп=');
CASE temp_pod_s OF
2000: ShowString(0,12,0,'КЗ ');
2001: ShowString(0,12,0,'Обр ');
2002: ShowString(0,13,0,'Ош. ');
ELSE
ShowReal(0, 12, 0, '%3.1f',temp_pod);
END_CASE;
ShowString(0,0,1,'Uуп='); ShowReal(0, 4, 1, '%4.2f',NaprReg*10);
END_IF;
Когда контроллер поддерживает целое значение температуры теплоносителя, например 50 гр., то точность становится 1 гр.: от 49,5 до 50,5 гр. Если поддерживается, например 50,5 гр. о точность становится 0,5 гр.: от 50,25 до 50,75 гр.
Где нужно подкорректировать программу чтобы точность поддержания температуры была 0,5 гр. для целых значений температур?
Добрый день.
CodeSys Version 2.3.9.41 + ПЛК63-М (target_v 2.01), в режиме эмулятора, автоматически не инициализируются конфигурационные значения по умолчанию в SubMenu конфигурации.
Это глюк или нет?