PDA

Просмотр полной версии : ВОПРОС-ОТВЕТ (отвечаем на простые вопросы от новичков)



Страницы : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 [42]

Спорягин Кирилл
16.01.2024, 16:05
Хотя, конечно, можно и любую другую скаду брать!

МихаилГл
16.01.2024, 16:08
Не слушайте.
Берите Мастерскаду 4Д.
То, что нужно для непрограммистов. Это как раз среда проектирования!
Все там отлично! Это просто излюбленная наша традиция охаивать все свое!

Зачем в неё тогда добавлен st... Она как раз ориентирована и на программистов. И да, 2 гигабайта это тоже минус.

Для модбас управления вполне сгодится рапидскада. Весит 20 мегабайт, бесплатна, изучить можно за 2..3 дня.

kondor3000
16.01.2024, 16:16
Не слушайте.
Берите Мастерскаду 4Д.
То, что нужно для непрограммистов. Это как раз среда проектирования!
Все там отлично! Это просто излюбленная наша традиция охаивать все свое!

Как можно новичкам советовать Мастерскаду 4D ? В ней спецы разбираются неделями, и всё равно она глючит и тормозит. Новичку это якорь на годы вперёд.

Traveller
16.01.2024, 16:54
Любую Скаду можно использовать или например Овен OPC сервер. Только возьмете скаду попроще, типа SimpLighte (есть бесплатные версии), простая и удобная, встроенный Модбас сервер https://simplight.ru

Мастерскады 4Д не берите, сырая, глючная хрень, а весит как чугунный мост.
Ок. будем изучать вопрос, просто пока разрабатываю концепцию, как будет лучше реализовывать проект...

Благодарю за подсказку! :)

atomo2
24.01.2024, 11:26
Добрый день, подскажите новичку пожалуйста.

Какой я адрес должен указать в EasyBuilder на кнопке старт (Вентилятора В1) ? Если в codesys у меня Start_Main_Fan_V1 AT %QX8 29.0.0: BOOL 73073 73072

petera
24.01.2024, 11:42
Добрый день, подскажите новичку пожалуйста.

Какой я адрес должен указать в EasyBuilder на кнопке старт (Вентилятора В1) ? Если в codesys у меня Start_Main_Fan_V1 AT %QX8 29.0.0: BOOL 73073 73072

Адрес зависит не от AT %QX8 29.0.0, а от расположения модулей в конфигурации слейва
Адреса начинаются с 0
https://owen.ru/forum/attachment.php?attachmentid=12345&d=1395648726

Cs-Cs
29.01.2024, 13:23
Камрады, подскажите и мне!
Подозреваю, что нарвался на выравнивание адресов в структуре и туплю, так как в другом проекте всё было нормально, и никаких глюков с выравниванием не было.
Вот что у меня есть:
1. Структура с описанием полей панели. Там всякие WORD или структуры из WORD. FLOAT и DWORD нет ВООБЩЕ.
2. Конфигурация ПЛК, где вбита пачка элементов по "4 Bytes".
3. ИП320.

Что наблюдаю: Начиная с регистра 26 данные съезжают на 1 регистр вперёд.
При этом панель читает правильно: если вручную в конфигурации ПЛК задать "2" на регистре 27 - то панель этот статус читает верно, чёрт побери.
Как будто моя структура сдвигается в регистрах 26-27 на 1 слово.

В CodeSys 2.3 как-то можно структуру выровнять по 2 байта, а не по 4 байта?
73165 73166 73167 73168

kondor3000
29.01.2024, 13:39
Камрады, подскажите и мне!
Подозреваю, что нарвался на выравнивание адресов в структуре и туплю, так как в другом проекте всё было нормально, и никаких глюков с выравниванием не было.
Вот что у меня есть:
1. Структура с описанием полей панели. Там всякие WORD или структуры из WORD. FLOAT и DWORD нет ВООБЩЕ.
2. Конфигурация ПЛК, где вбита пачка элементов по "4 Bytes".
3. ИП320.

Что наблюдаю: Начиная с регистра 26 данные съезжают на 1 регистр вперёд.
При этом панель читает правильно: если вручную в конфигурации ПЛК задать "2" на регистре 27 - то панель этот статус читает верно, чёрт побери.
Как будто моя структура сдвигается в регистрах 26-27 на 1 слово.

В CodeSys 2.3 как-то можно структуру выровнять по 2 байта, а не по 4 байта?


Так она и сдвигается, последний регистр WORD - 26 регистр , а 32 битная начинается с нечётного 27, а должна быть с чётного ( сдвигается на 28)
Пустой WORD можно просто вставить в конце предыдущей структуры, будет 27.

Cs-Cs
29.01.2024, 13:50
А где у меня 32 бита? У меня везде всё по WORD - по 16 бит же.
И панель всё читает как 16-битные. Какая ей разница, как в ПЛК ЭТО вбито? В прошлом проекте такого не было, и начало регистров с нечётными данными читались на ура.
То, что я тут поменял - так это сделал вложенные структуры из 2х WORD на 4 WORD.

kondor3000
29.01.2024, 14:08
4 BYTE, это DWORD, а структуру вы пытаетесь поместить во 2 регистр предыдущего DWORD.

Cs-Cs
29.01.2024, 14:22
4 BYTE, это DWORD, а структуру вы пытаетесь поместить во 2 регистр предыдущего DWORD. Не понимаю. Почему ж в другом проекте я делал так:
* Набивал в конфигурации ПЛК по 4 байта (DWORD)
* Читал их как хотел из панели: чётно или нечётно, и панель всё читала.

А тут откуда-то вылезают дырки в самой структуре в CodeSys, а не в панели.
Я ща начал при помощи SizeOf() подгонять всё под количество полей в своей структуре.

kondor3000
29.01.2024, 14:28
Не понимаю. Почему ж в другом проекте я делал так:
* Набивал в конфигурации ПЛК по 4 байта (DWORD)
.

А саму структуру CSSetTimesBE, скрин можете выложить?

Cs-Cs
29.01.2024, 14:44
Да, конечно. И можно на "ты", без проблем.
Как я понял, CodeSys в своих структурах округляет новые поля (вложеные структуры), если они начинаются с нечётного адреса.


(* Структура данных для интервалов времени настроек объектов на панели оператора или в другом месте.
Занимает 4 (ЧЕТЫРЕ) регистра *)
TYPE CSSetTimesBE :
STRUCT
TimeBeginHour : WORD; (* Регистр 1, Время начала интервала: Часы *)
TimeBeginMinute : WORD; (* Регистр 2, Время начала интервала: Минуты *)
TimeEndHour : WORD; (* Регистр 3, Время конца интервала: Часы *)
TimeEndMinute : WORD; (* Регистр 4, Время конца интервала: Минуты *)
END_STRUCT
END_TYPE

Cs-Cs
29.01.2024, 15:52
Валенок Спасибо! Я вот и влетел именно со стороны CodeSys с этими размерами и округлением структур.
Ща правлю всё понемногу, проверяя через SizeOf!

Cs-Cs
29.01.2024, 16:56
Ура! Я разобрался с этим выравниванием. В итоге число регистров и 520 стало 542 штуки. ИП-320 это нормально сожрала.
Так что всё ОК: проблемы были именно с выравниванием структур, а не с конфигурацией ПЛК.

1exan
30.01.2024, 04:53
Ура! Я разобрался с этим выравниванием. В итоге число регистров и 520 стало 542 штуки. ИП-320 это нормально сожрала.
Так что всё ОК: проблемы были именно с выравниванием структур, а не с конфигурацией ПЛК.

Тоже попался на этом размере структур. Причём в эмуляции такая структура имеет размер 2 байта, а после загрузки в ПЛК - уже 4

Cs-Cs
30.01.2024, 10:58
Тоже попался на этом размере структур. Причём в эмуляции такая структура имеет размер 2 байта, а после загрузки в ПЛК - уже 4
Угу! Я вчера в итоге через SizeOf и Эксель подбирал структуры так, чтобы адреса совпадали =)
Ну, образно вижу что по Экселю должно быть 118, а по ПЛК - 120. Значит где-то WORD дополнился. Иду его искать по чётным и нечётным адресам. Нахожу. Проверяю ещё раз. Совпадает - отлично.

senkos
03.02.2024, 23:38
Здравствуйте, коллеги.
Прошу помощи, в оптимизации кода. Возможно ли данный код привести к циклу чтобы реализовывать любое количество START_MOTOR


IF Conveyors[2].motorSensor THEN
START_MOTOR1(inStart:=Conveyors[1].motorStart, inReset:=Conveyors[1].motorStop);
Conveyors[1].motorSensor := START_MOTOR1.OUT;
END_IF
IF Conveyors[3].motorSensor THEN
START_MOTOR2(inStart:=Conveyors[2].motorStart, inReset:=Conveyors[2].motorStop);
Conveyors[2].motorSensor := START_MOTOR2.OUT;
END_IF
IF Conveyors[4].motorSensor THEN
START_MOTOR3(inStart:=Conveyors[3].motorStart, inReset:=Conveyors[3].motorStop);
Conveyors[3].motorSensor := START_MOTOR3.OUT;
END_IF


я пытаюсь делать в цикле но при любом Conveyors[i+1].motorSensor = TRUE все START_MOTOR срабатывают


FOR i := 1 TO count - 1 DO
IF Conveyors[i+1].motorSensor THEN
START_MOTOR(inStart:=Conveyors[i].motorStart, inReset:=Conveyors[i].motorStop);
Conveyors[i].motorSensor := START_MOTOR.OUT;
END_IF
END_FOR

capzap
04.02.2024, 07:11
Здравствуйте, коллеги.
Прошу помощи, в оптимизации кода. Возможно ли данный код привести к циклу чтобы реализовывать любое количество START_MOTOR


IF Conveyors[2].motorSensor THEN
START_MOTOR1(inStart:=Conveyors[1].motorStart, inReset:=Conveyors[1].motorStop);
Conveyors[1].motorSensor := START_MOTOR1.OUT;
END_IF
IF Conveyors[3].motorSensor THEN
START_MOTOR2(inStart:=Conveyors[2].motorStart, inReset:=Conveyors[2].motorStop);
Conveyors[2].motorSensor := START_MOTOR2.OUT;
END_IF
IF Conveyors[4].motorSensor THEN
START_MOTOR3(inStart:=Conveyors[3].motorStart, inReset:=Conveyors[3].motorStop);
Conveyors[3].motorSensor := START_MOTOR3.OUT;
END_IF


я пытаюсь делать в цикле но при любом Conveyors[i+1].motorSensor = TRUE все START_MOTOR срабатывают


FOR i := 1 TO count - 1 DO
IF Conveyors[i+1].motorSensor THEN
START_MOTOR(inStart:=Conveyors[i].motorStart, inReset:=Conveyors[i].motorStop);
Conveyors[i].motorSensor := START_MOTOR.OUT;
END_IF
END_FOR


Наверное плюс один не везде выставляете

МихаилГл
04.02.2024, 07:15
Start motor должен быть массивом, а у вас один параметр при изменении кода.

Не заметил что это fb.

Тогда другой вариант... А если в коде первоначальном fb с цифровым индексом заменить на один и тот же fb, как себя поведёт программа? Если так же как программа с циклом, то проблема где то там...

Dimensy
04.02.2024, 09:51
Здравствуйте, коллеги.
Прошу помощи, в оптимизации кода. Возможно ли данный код привести к циклу чтобы реализовывать любое количество START_MOTOR


IF Conveyors[2].motorSensor THEN
START_MOTOR1(inStart:=Conveyors[1].motorStart, inReset:=Conveyors[1].motorStop);
Conveyors[1].motorSensor := START_MOTOR1.OUT;
END_IF
IF Conveyors[3].motorSensor THEN
START_MOTOR2(inStart:=Conveyors[2].motorStart, inReset:=Conveyors[2].motorStop);
Conveyors[2].motorSensor := START_MOTOR2.OUT;
END_IF
IF Conveyors[4].motorSensor THEN
START_MOTOR3(inStart:=Conveyors[3].motorStart, inReset:=Conveyors[3].motorStop);
Conveyors[3].motorSensor := START_MOTOR3.OUT;
END_IF


я пытаюсь делать в цикле но при любом Conveyors[i+1].motorSensor = TRUE все START_MOTOR срабатывают


FOR i := 1 TO count - 1 DO
IF Conveyors[i+1].motorSensor THEN
START_MOTOR(inStart:=Conveyors[i].motorStart, inReset:=Conveyors[i].motorStop);
Conveyors[i].motorSensor := START_MOTOR.OUT;
END_IF
END_FOR


А разве может один экземпляр ФБ параллельно работать с несколькими группами значений?
Наверное, все-таки надо объявить массив
START_MOTOR: ARRAY [1..10] OF fbSTART_MOTOR;

senkos
04.02.2024, 12:23
А разве может один экземпляр ФБ параллельно работать с несколькими группами значений?
Наверное, все-таки надо объявить массив
START_MOTOR: ARRAY [1..10] OF fbSTART_MOTOR;

Благодарю вас! Это то что нужно и удалось реализовать расширяемость системы.


FOR i := 1 TO count - 1 DO
IF Conveyors[i+1].motorSensor THEN
START_MOTORS[i](inStart:=Conveyors[i].motorStart, inReset:=Conveyors[i].motorStop);
Conveyors[i].motorSensor := START_MOTORS[i].OUT;(*Имитируем ответный сигнал что конвейер запустился*)
END_IF
END_FOR

Валенок
04.02.2024, 13:08
Благодарю вас! Это то что нужно и удалось реализовать расширяемость системы.


FOR i := 1 TO count - 1 DO
IF Conveyors[i+1].motorSensor THEN
START_MOTORS[i](inStart:=Conveyors[i].motorStart, inReset:=Conveyors[i].motorStop);
Conveyors[i].motorSensor := START_MOTORS[i].OUT;(*Имитируем ответный сигнал что конвейер запустился*)
END_IF
END_FOR

Я вот всего кода невижу, но СТАРТМОТОР (который фб) здесь не работает когда следующий конвейр не того.
Так задумано?

В этой цепочке последовательных разрешений порвите что нибудь по середине нештатно, какую нить обратную связь.

senkos
05.02.2024, 23:14
Я вот всего кода невижу, но СТАРТМОТОР (который фб) здесь не работает когда следующий конвейр не того.
Так задумано?


Да, все верно, когда следующий конвейер останавливается, то, коробка доходит до конца текущего конвейера и он останавливается. И наоборот при включении следующего, возобновляется движение предыдущего. Вроде реализовал, теперь бьюсь с визуализацией в Codesys

МихаилГл
06.02.2024, 00:29
Да, все верно, когда следующий конвейер останавливается, то, коробка доходит до конца текущего конвейера и он останавливается. И наоборот при включении следующего, возобновляется движение предыдущего. Вроде реализовал, теперь бьюсь с визуализацией в Codesys

В версии 2.3? Или на скаде какой нибудь? Просто в кодесисе 2.3 визуализация вроде только в среде...

senkos
06.02.2024, 23:06
В версии 2.3? Или на скаде какой нибудь? Просто в кодесисе 2.3 визуализация вроде только в среде...

в кодесисе 2.3, мне чисто теория и примерный алгоритм нужен сейчас, в приложенном примере таргет для PLC110.30m(v2)

atomo2
08.02.2024, 11:19
Добрый день, кто нибудь делал связку PLC овен 110-60 и бпс-3-и с газоанализаторами СТГ-3 в codesys 2.3? Не получается получить данные с бпс3

In_Da_Cher_A
08.02.2024, 16:29
Добрый день, кто нибудь делал связку PLC овен 110-60 и бпс-3-и с газоанализаторами СТГ-3 в codesys 2.3? Не получается получить данные с бпс3я не делал, просто рядом постоял
если мне не изменяет память - там модбас, основные общие данные спокойно можно прочитать, там обычный byte, делайте UMD и считывайте и распаковывайте
а если хотите всю детализацию, то и там и в СТГ тоже формат BCD, там 4 байта , тут надо уже глубоко погружаться . хотя это как и DWORD в принципе, но там надо повозиться с распаковкой и придёться скорее всего вручную это писать
и зачем вам СТГ напрямую? он же адресный, для подключения к БПС

Easy_Enemy
12.02.2024, 16:12
Больше нет сил! Ткните носом, пожалуйста. Управление вентиляцией представлена структурой. В отдельном ФБ - все функции системы. Есть функция управления заслонкой без обратной связи с отслеживанием позиции по времени ее работы:
FUNCTION_BLOCK VenFunctions
VAR_INPUT
num : INT;
END_VAR
--------------------
...
IF Ven[num].Flap.Open THEN
IF Ven[num].Flap.Open AND NOT Ven[num].Flap.xOpen THEN
Ven[num].Flap.xOpen:=TRUE;
Ven[num].Flap.Close:=Ven[num].Flap.xClose:=FALSE;
Ven[num].Flap.t_Pos:=TIME();
ELSIF Ven[num].Flap.Open AND Ven[num].Flap.xOpen THEN
Ven[num].Flap.Pos:= Ven[num].Flap.Pos + 0.00258 * (TIME_TO_REAL(TIME() - Ven[num].Flap.t_Pos));
Ven[num].Flap.t_Pos:=TIME();
IF Ven[num].Flap.Pos > 90 THEN Ven[num].Flap.Pos:=90;
END_IF;
ELSE
Ven[num].Flap.xOpen:=FALSE;
END_IF;
END_IF;
...
Тоже самое и на закрытие. Отлично работает, видно включение выхода на ПЛК, видно движение в визуализации.
Вчера написал режим калибровки/антизалипания (время от времени полностью открывать, потом закрывать для синхронизации положения) и проблема, в том, что, по каким-то причинам данный функция пытается выполниться за 1 цикл ПЛК, то есть не записывает выходные переменные. Подскажите, как обыграть данную ситуёвину( Максимально упрощенный блок калибровки:

IF Ven[num].Flap.xAdjust THEN (* Пора калиброваться *)
CASE Ven[num].Flap.sAdjust OF (* Счетчик шагов в структуре *)
1: Ven[num].Flap.Close:=FALSE; (*Шаг 1, Открываем заслонку, понадобится 40 секунд с запасом *)
VEN[num].Flap.Open:=TRUE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1.in:=FALSE;
END_IF;
2: VEN[num].Flap.Close:=TRUE; (*Шаг 2, Закрываем заслонку, те же 40 секунд *)
VEN[num].Flap.Open:=FALSE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1.in:=FALSE;
END_IF;
3: VEN[num].Flap.Close:=FALSE; (*Шаг 3 Выключаем управление *)
VEN[num].Flap.Open:=FALSE;
Ven[num].Flap.sAdjust:=1; (* Сбрасываем счетчик *)
Ven[num].Flap.xAdjust:=FALSE; (* Завершаем режим калибровки *)
END_CASE
END_IF;

(В программе управления вентиляцией объявляем этот ФБ, как входной параметр указываем номер системы - V1(num:=1); )
Перепробовал RETURN, убрать CASE за IF.. не могу осилить :/
Да, и еще момент - через визиализацию видно, что таймеры работают, так как шаги шагаются ( Ven[num].Flap.sAdjust увеличивается, как положено ), но значения на вход не пишутся

kondor3000
12.02.2024, 16:24
(В программе управления вентиляцией объявляем этот ФБ, как входной параметр указываем номер системы - V1(num:=1); )
Перепробовал RETURN, убрать CASE за IF.. не могу осилить :/
Да, и еще момент - через визиализацию видно, что таймеры работают, так как шаги шагаются ( Ven[num].Flap.sAdjust увеличивается, как положено ), но значения на вход не пишутся

Проект выложите, в расширенном режиме, добавить файл.

Easy_Enemy
12.02.2024, 16:37
Проект выложите, в расширенном режиме, добавить файл.
Зачистил все лишнее.


мало записать t1.in:=FALSE; надо еще и выполнить, поэтому лучше пишите t1(IN:=FALSE, PT:=t1.PT);
это просто рекомендация, имеет ли она отношение к проблеме, не знаю

Обычно таймерами не пользуюсь, просто пишу текущее время в переменную, и потом сравниваю, это уже от безысходности, но, попробую, спасибо!

1exan
12.02.2024, 17:03
мало записать t1.in:=FALSE; надо еще и выполнить, поэтому лучше пишите t1(IN:=FALSE, PT:=t1.PT);
это просто рекомендация, имеет ли она отношение к проблеме, не знаю

Это точно имеет к этому отношение

И ещё сходу не увидел, где инициализируется переменная case "Ven[num].Flap.sAdjust" (изначально она имеет значение 0, а case указаны только для значений 1...3)?

Easy_Enemy
12.02.2024, 17:20
Это точно имеет к этому отношение

И ещё сходу не увидел, где инициализируется переменная case "Ven[num].Flap.sAdjust" (изначально она имеет значение 0, а case указаны только для значений 1...3)?

С таймером - не прокатило.. Изначально, управление сложнее, с бОльшим кол-вом переменных, через TIME(). Чтобы не отнимать время на кучу кода - втыкнул таймер.
Про Adjust - да, прошу прощения: это пытался вывести CASE за условие IF (Если нужна калибровка, то Adjust =1, иначе 0, энд иф. И уже далее - просто кейс. Так тоже не сработало). Вернул счет с единички - тоже самое: при калибровке - система стоит. Уже попробовал ОТКР/ЗАКР вынести в отдельную функцию, а фб оставить чисто на такие модули с таймерами. Результат тот же..

1exan
12.02.2024, 17:24
С таймером - не прокатило.. Изначально, управление сложнее, с бОльшим кол-вом переменных, через TIME(). Чтобы не отнимать время на кучу кода - втыкнул таймер.
Про Adjust - да, прошу прощения: это пытался вывести CASE за условие IF (Если нужна калибровка, то Adjust =1, иначе 0, энд иф. И уже далее - просто кейс. Так тоже не сработало). Вернул счет с единички - тоже самое: при калибровке - система стоит. Уже попробовал ОТКР/ЗАКР вынести в отдельную функцию, а фб оставить чисто на такие модули с таймерами. Результат тот же..

Покажете вариант, в котором не прокатило?

Easy_Enemy
12.02.2024, 17:36
Покажете вариант, в котором не прокатило?



IF Ven[num].Flap.xAdjust THEN (* Выносим Case за IF *)
Ven[num].Flap.sAdjust:=1;
ELSE
Ven[num].Flap.sAdjust:=0;
END_IF;

CASE Ven[num].Flap.sAdjust OF (*то же, без цикла IF*)
1: Ven[num].Flap.Close:=FALSE; (*Шаг 1*)
VEN[num].Flap.Open:=TRUE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE, PT:=t1.PT);
END_IF;
2: VEN[num].Flap.Close:=TRUE; (* Шаг 2*)
VEN[num].Flap.Open:=FALSE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE, PT:=t1.PT);
END_IF;
3: VEN[num].Flap.Close:=FALSE; (* Шаг 3*)
VEN[num].Flap.Open:=FALSE;
Ven[num].Flap.sAdjust:=0; (* Сбрасыываем все *)
Ven[num].Flap.xAdjust:=FALSE;
END_CASE



Думал ошибка инициации ФБ, уже намертво прибил Ven[1], но, с другой стороны, все 9 заслонок открываются/закрываются, значит все ок.. воткнуть RETURN после каждого шага, чтобы, условно, "не ждать сейчас таймер, заглянем потом" - так же не дают результата..




IF Ven[num].Flap.sAdjust = 1 THEN
Ven[num].Flap.Close:=FALSE;
VEN[num].Flap.Open:=TRUE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE, PT:=t1.PT);
END_IF;
END_IF;
IF Ven[num].Flap.sAdjust = 2 THEN
VEN[num].Flap.Close:=TRUE;
VEN[num].Flap.Open:=FALSE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE, PT:=t1.PT);
END_IF;
END_IF;
IF Ven[num].Flap.sAdjust = 3 THEN
VEN[num].Flap.Close:=FALSE;
VEN[num].Flap.Open:=FALSE;
Ven[num].Flap.sAdjust:=0;
Ven[num].Flap.xAdjust:=FALSE;
END_IF;


Тоже самое, но без CASE. Не катит..

МихаилГл
12.02.2024, 17:39
У вас переменная bool, а вы её в кейс засунули как переменную инт, и она в первом иф всегда 1...
Пардон, там x... и s...
Выносите таймеры из кейса.

Если честно, кровь из глаз чуть не пошла от этого кода. Ничего там не понял... Вернее впал в спупор.

Вы же в кодесисе... Таймеры запускаются? В кейсах или ифах сделайте переменную равную тру, у уже ей запускайте таймер вне условий. Сброс таймеров можете таким же оставить, но только с командой фальш без задания времени.


t1(IN:=парарам, PT:=T#40s);
IF Ven[num].Flap.sAdjust = 1 THEN
Ven[num].Flap.Close:=FALSE;
VEN[num].Flap.Open:=TRUE;
Парарам :=тру;
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE);
END_IF;
END_IF;
И т.д.



IF Ven[num].Flap.sAdjust = 2 THEN
VEN[num].Flap.Close:=TRUE;
VEN[num].Flap.Open:=FALSE;
t1(IN:=TRUE, PT:=T#40s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=Ven[num].Flap.sAdjust+1;
t1(IN:=FALSE, PT:=t1.PT);
END_IF;
END_IF;
IF Ven[num].Flap.sAdjust = 3 THEN
VEN[num].Flap.Close:=FALSE;
VEN[num].Flap.Open:=FALSE;
Ven[num].Flap.sAdjust:=0;
Ven[num].Flap.xAdjust:=FALSE;
END_IF;



И ещё одно замечание:
T1[I](IN:=парарам[I], PT:=T#40s);

1exan
12.02.2024, 19:08
...


Думал ошибка инициации ФБ, уже намертво прибил Ven[1], но, с другой стороны, все 9 заслонок открываются/закрываются, значит все ок.. воткнуть RETURN после каждого шага, чтобы, условно, "не ждать сейчас таймер, заглянем потом" - так же не дают результата..




...


Тоже самое, но без CASE. Не катит..

Наверно такое хотели получить:


IF Ven[num].Flap.xAdjust THEN (* Выносим Case за IF *)
IF Ven[num].Flap.sAdjust=0 THEN Ven[num].Flap.sAdjust:=1; END_IF;
ELSE
Ven[num].Flap.sAdjust:=0;
END_IF;

CASE Ven[num].Flap.sAdjust OF (*то же, без цикла IF*)
1: Ven[num].Flap.Close:=FALSE; (*Шаг 1*)
VEN[num].Flap.Open:=TRUE;
t1(IN:=TRUE, PT:=T#10s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=2;
t1(IN:=FALSE);
END_IF;
2: VEN[num].Flap.Close:=TRUE; (* Шаг 2*)
VEN[num].Flap.Open:=FALSE;
t1(IN:=TRUE, PT:=T#10s);
IF t1.q THEN
Ven[num].Flap.sAdjust:=3;
t1(IN:=FALSE);
END_IF;
3: VEN[num].Flap.Close:=FALSE; (* Шаг 3*)
VEN[num].Flap.Open:=FALSE;
Ven[num].Flap.sAdjust:=0; (* Сбрасыываем все *)
Ven[num].Flap.xAdjust:=FALSE;
END_CASE


(*Функция открытия заслонки*)
IF Ven[num].Flap.Open THEN
IF Ven[num].Flap.Open AND NOT Ven[num].Flap.xOpen THEN
Ven[num].Flap.xOpen:=TRUE;
Ven[num].Flap.Close:=Ven[num].Flap.xClose:=FALSE;
Ven[num].Flap.t_Pos:=TIME();
ELSIF Ven[num].Flap.Open AND Ven[num].Flap.xOpen THEN
Ven[num].Flap.Pos:= Ven[num].Flap.Pos + 0.00258 * (TIME_TO_REAL(TIME() - Ven[num].Flap.t_Pos));
Ven[num].Flap.t_Pos:=TIME();
IF Ven[num].Flap.Pos > 90 THEN Ven[num].Flap.Pos:=90;
END_IF;
ELSE
Ven[num].Flap.xOpen:=FALSE;
END_IF;
END_IF;

(* Функция закрытия заслонки *)
IF Ven[num].Flap.Close THEN
IF Ven[num].Flap.Close AND NOT Ven[num].Flap.xClose THEN
Ven[num].Flap.xClose:=TRUE;
Ven[num].Flap.xOpen:= FALSE;
Ven[num].Flap.t_Pos:=TIME();
ELSIF Ven[num].Flap.Close AND Ven[num].Flap.xClose THEN
Ven[num].Flap.Pos:= Ven[num].Flap.Pos - 0.00258 * (TIME_TO_REAL(TIME() - Ven[num].Flap.t_Pos));
Ven[num].Flap.t_Pos:=TIME();
IF Ven[num].Flap.Pos < 0 THEN Ven[num].Flap.Pos:=0;
END_IF;
ELSE
Ven[num].Flap.xClose:=FALSE;
END_IF;
END_IF;





А какая вообще функция у данного механизма и зачем нужна калибровка?

Easy_Enemy
12.02.2024, 19:09
У вас переменная bool, а вы её в кейс засунули как переменную инт, и она в первом иф всегда 1...
Пардон, там x... и s...
Выносите таймеры из кейса.

Если честно, кровь из глаз чуть не пошла от этого кода. Ничего там не понял... Вернее впал в спупор.

Вы же в кодесисе... Таймеры запускаются? В кейсах или ифах сделайте переменную равную тру, у уже ей запускайте таймер вне условий. Сброс таймеров можете таким же оставить, но только с командой фальш без задания времени.

Таймеры и внутри и за CASE - работают. Работает и счетчик шагов, но не присваивались значения на выходы ПЛК..

Опыт путем выяснил следующее: если в цикл запихнуть переменную, привязанную, непосредственно к выходу ПЛК - все работает. Если (как в моем случае) - это именно функция управления - не хочет ее обработать, что достаточно печально.. Будем разбираться, как это обходить..




И ещё одно замечание:
T1[I](IN:=парарам[I], PT:=T#40s);


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


...
Ven[num].Flap.tMove:=TIME(); (*Присваиваем текущую временную метку*)
...
IF (TIME() - Ven[num].Flap.tMove) >= Ven[num].Flap.lMove THEN (*Если текущее время плк минус временная метка больше-равно нужной, то..*)
Ven[num].Flap.sAdjust:=3;
Ven[num].Flap.tMove:=TIME(); (*Обновляем метку, если нужно*)
END_IF;





А какая вообще функция у данного механизма и зачем нужна калибровка?

Это заслонки воздуховодов одновременно, приточки, кондеев и парогенератора. То есть, помимо регулировки воздушного потока "по восстребованию", они играют роль предохранителя от затопления воздуховодов увлажнителем, если авария у УК и отвалится подача, упадет качество воздуха (докинуть свежего), факторов уйма. А калибровка - банально нет датчиков положения, есть только концевики внутри самого привода. Все равно позиционирование будет копить ошибки и раз в месяц-пару нужно синхронить положение. Плюс "не залипнут", если в одном положении давно, что уже бывало..

Валенок
12.02.2024, 20:03
а накой уходить в 3й шаг? заради выключить выходы?
зачем мутилово с IF перед case? шаг 0 в case может быть из ";"
чего флапу не сделать свой action где он это все без ven[num].flap.

Easy_Enemy
12.02.2024, 20:24
а накой уходить в 3й шаг? заради выключить выходы?
Порядок такой - запоминаем текущее положение -> открываемся -> закрываемся -> возвращаемся туда, "где вроде было ок" -> отстаиваемся чуть -> передаем управление обратно ПИДу. Это уже упрощенный варик, чтоб хоть как-то заставить сиё работать..



зачем мутилово с IF перед case? шаг 0 в case может быть из ";"

просто тест, мало ли.. с учетом перепробаванных вариантов - почему нет..



чего флапу не сделать свой action где он это все без ven[num].flap.

Заслонок 9 (помещений), по 2 выхода на штуку (18). Помимо них - еще куча мишуры, пресущей данным помещениям. И не хотелось бы возиться с каждым такой штукой отдельно, собственно, было написано маппирование, а управление - через циклы и аттрибуты через точки

Easy_Enemy
12.02.2024, 20:55
... было написано маппирование, а управление - через циклы и аттрибуты через точки

А вот и проблема.. есть выход, который управляет сигналом на открытие. В "конфигурации ПЛК" назвал его Flap1Open (пробовал там же переносить в глобальные и прибивать гвоздями через AT - тоже самое). В функции карты присвоил его в массив Ven[1].Flap.Open:=Flap1Open (почему-то не наоборот). Так нормально работает функция управления на открытие, но в режиме калибровки значение на сам выход не записывается. Но, если поменять местами Flap1Open:=Ven[1].Flap.Open, то режим открытия работать перестает, а вот в калибровке - выход включается, но не выключается по таймеру (функция - одна и та же). Чертовщина..

Easy_Enemy
13.02.2024, 00:54
Кривой кодесис, глючный Овен, да?
А всего-то - убрать лес. И сразу будут видны деревья.

Помимо небольшой оптимизации и пары интересностей с CASE - проблема не особо решилась. То есть, я так понимаю, из вышестоящих (управляющих систем) - обращение к переменным примерно то же, что моя "кровь из глаз", но, как минимум ясна структура (система, номер, девайс, атрибут). При обработке 20+ разных систем - становится понятнее. Мне не в падлу расписать. Как минимум, Вы за 10 минут поняли "что-куда" и поправили. По быстродействию: утверждать не могу, пока доделки не будут доделаны - нельзя запустить тест на скорость цикла ПЛК. Кодесис 2.3 - банально, старый. К овену претензий нет, кроме, немного усложненной документации.

1exan
13.02.2024, 04:34
А вот и проблема.. есть выход, который управляет сигналом на открытие. В "конфигурации ПЛК" назвал его Flap1Open (пробовал там же переносить в глобальные и прибивать гвоздями через AT - тоже самое). В функции карты присвоил его в массив Ven[1].Flap.Open:=Flap1Open (почему-то не наоборот). Так нормально работает функция управления на открытие, но в режиме калибровки значение на сам выход не записывается. Но, если поменять местами Flap1Open:=Ven[1].Flap.Open, то режим открытия работать перестает, а вот в калибровке - выход включается, но не выключается по таймеру (функция - одна и та же). Чертовщина..

Режим калибровки надо ставить ДО блоков кода управления выходами. Иначе значения управления, записанные в коде калибровки перезаписываются значениями, полученными от кнопок управления визуализации (я же приводил вам код выше)

МихаилГл
13.02.2024, 05:03
Вот просто фрагмент:

IF Close THEN
IF Close AND NOT xClose THEN
xClose:=TRUE;
xOpen:= FALSE;
t_Pos:=TIME();
ELSIF Close AND xClose THEN
Pos:= Pos - 0.00258 * (TIME_TO_REAL(TIME() - t_Pos));
t_Pos:=TIME();
IF Pos < 0 THEN Pos:=0;
END_IF;
ELSE
xClose:=FALSE;
END_IF;
END_IF
Это чего? удаляем


IF Close THEN
IF NOT xClose THEN
xClose:=TRUE;
xOpen:= FALSE;
t_Pos:=TIME();
ELSIF xClose THEN
Pos:= Pos - 0.00258 * (TIME_TO_REAL(TIME() - t_Pos));
t_Pos:=TIME();
IF Pos < 0 THEN Pos:=0;
END_IF;
ELSE
xClose:=FALSE;
END_IF;
END_IF

Просто ELSE
А как думаете это когда то будет? А тут нету проблемы? Вы решайте.

Похоже это к предыдущему IF...
Да, интересно смотреть чужие коды, много нового узнаешь. Иногда полезно.

capzap
13.02.2024, 07:45
нельзя запустить тест на скорость цикла ПЛК. Кодесис 2.3 - банально, старый.

Возможно, не КДС, а Вы такой старый что поленились дочитать до конца документацию https://owen.ru/uploads/373/plc1xx_plcconfiguration_v2.0.pdf раздел 3.8

capzap
13.02.2024, 07:49
Вот просто фрагмент:

IF Close THEN
IF Close AND NOT xClose THEN
xClose:=TRUE;
xOpen:= FALSE;
t_Pos:=TIME();
ELSIF Close AND xClose THEN
Pos:= Pos - 0.00258 * (TIME_TO_REAL(TIME() - t_Pos));
t_Pos:=TIME();
IF Pos < 0 THEN Pos:=0;
END_IF;
ELSE
xClose:=FALSE;
END_IF;
END_IF
скорее всего это родилось из этого и неуемного желания использовать метод тыка: "а вдруг заработает"


IF Close AND NOT xClose THEN
xClose:=TRUE;
xOpen:= FALSE;
t_Pos:=TIME();
ELSIF Close THEN
Pos:= Pos - 0.00258 * (TIME_TO_REAL(TIME() - t_Pos));
t_Pos:=TIME();
IF Pos < 0 THEN Pos:=0;
END_IF;
END_IF;
xClose := Close;

Easy_Enemy
14.02.2024, 20:10
скорее всего это родилось из этого и неуемного желания использовать метод тыка: "а вдруг заработает"

Именно так..



Возможно, не КДС, а Вы такой старый что поленились дочитать до конца документацию https://owen.ru/uploads/373/plc1xx_p...ation_v2.0.pdf раздел 3.8

Предпочитаю просто ставить временные метки по интересующим местам, со времен микроконтроллеров, но - да, не читал. Эт я к тому, что, пока все не будет дописано - нет особого смысла.



Режим калибровки надо ставить ДО блоков кода управления выходами. Иначе значения управления, записанные в коде калибровки перезаписываются значениями, полученными от кнопок управления визуализации (я же приводил вам код выше)

Пробовал, уже потом подумал про ошибку маппирования. Визуализация не мешалась, если ничего не трогать)

Вообще, выяснил следующее: функции работают (шаги шагают, таймеры таймерят) и, если указывать имена самих выходов - все отлично работает. То есть, если заглянуть в функцию map, то видно, что и переменная, которая должна передавать значение на выход так же переключается ( Ven[1].....open). Фактически, все свелось к тому, что нельзя запихать выход в массив. То есть, можно это обойти, если это простые дискретные выходы через ADR, но, видимо не канает с быстрыми..

Easy_Enemy
14.02.2024, 21:21
Это не будет работать в любом случае
А по поводу времени цикла, смотрите, если в середине написания кода цикл превысит разумные пределы, а за это время цикла Вы возьмётесь когда будет все написано, не обидно ли будет все переделывать?
С простыми дискретными - работает. Там можно сделать так: " Ven[3].Flap:= ADR(%QB3.0); " , а потом присвоить управление номеру бита нужного выхода, то есть у нас управление по прямому адресу, только что проверил. А вот с фастами, из-за того, что это чистый BOOL в CdS 2* - нельзя, ADR хочет BYTE +. Сейчас просто найду, с чем можно поменять местами эти заслонки. В целом - вопрос решен. Хотелось бы, все-таки разобраться, как можно быстрые дискретники удобно обрабатывать, но уже потом.. Спасибо всем за помощь, безусловно, появилась пища для размышления.



А по поводу времени цикла, смотрите, если в середине написания кода цикл превысит разумные пределы, а за это время цикла Вы возьмётесь когда будет все написано, не обидно ли будет все переделывать?
Можно сказать - намеренно: время - да, съедает, но, в основном - "учение через боль" лучше усваивается, иначе обленюсь)

capzap
15.02.2024, 08:02
можно сделать так: " Ven[3].Flap:= ADR(%QB3.0);

ни чего не понял, Flap это структура, начинающаяся с REAL, как Вы присваиваете ей(конкретно реалу) байт с дискретными переменными управления на открытие и закрытие?

1exan
15.02.2024, 08:38
...
Фактически, все свелось к тому, что нельзя запихать выход в массив. То есть, можно это обойти, если это простые дискретные выходы через ADR, но, видимо не канает с быстрыми..

Вероятность того, что структуры ваших внутренних объектов совпадут с типами и расположением физических входов и выходов в контроллере - приближается к нулю. Поэтому я например делаю так:

Объявляю глобальные переменные физических входов и выходов типа такого:


DI_1 AT %IX0.0 : BOOL; (* Дискретный вход 1 *)
DI_2 AT %IX0.1 : BOOL; (* Дискретный вход 2 *)
DI_3 AT %IX1.0.0 : BOOL; (* Дискретный вход 5 *)
DI_4 AT %IX1.0.1 : BOOL; (* Дискретный вход 6 *)
DI_5 AT %IX1.0.2 : BOOL; (* Дискретный вход 7 *)
DI_6 AT %IX1.0.3 : BOOL; (* Дискретный вход 8 *)
...

DO_1 AT %QX2.0 : BOOL; (* Дискретный выход 1 *)
DO_2 AT %QX2.1 : BOOL; (* Дискретный выход 2 *)
DO_3 AT %QX2.2 : BOOL; (* Дискретный выход 3 *)
DO_4 AT %QX2.3 : BOOL; (* Дискретный выход 4 *)
DO_5 AT %QX3.0.0 : BOOL; (* Дискретный выход 5 *)
DO_6 AT %QX3.0.1 : BOOL; (* Дискретный выход 6 *)
...

(можно конечно забить имена прямо в конфигурацию, но мне так удобнее, и нет проблем при смене конфигурации).

В отдельной программе, которая выполняется в отдельной задаче со свободным циклом выполнения делаю их присваивание/чтение:


arBlock[1]. xInStart := DI_5 ; (* *)
arBlock[1]. xInStop := DI_6 ; (* *)
...

DO_5 := arBlock[1]. xOutStart ; (* *)
DO_6 := arBlock[1]. xOutAlarm ; (* *)
...


Уж не знаю, насколько это "медленней" по сравнению с работой со входами/выходами через байты - но подозреваю, что несущественно.
Но при этом вы не привязаны к расположению входов/выходов в структурах и можно в любой момент "отключить" физические входы/выходы для, например, 'эмуляции процесса

Cs-Cs
15.02.2024, 09:41
Уж не знаю, насколько это "медленней" по сравнению с работой со входами/выходами через байты - но подозреваю, что несущественно.
Но при этом вы не привязаны к расположению входов/выходов в структурах и можно в любой момент "отключить" физические входы/выходы для, например, 'эмуляции процесса АБСОЛЮТНО соглаасен! Я так делаю прям вот всегда! У меня этому даже кусок статьи посвящён (рекомендую прочитать, без шуток): https://cs-cs.net/technologii-testirovaniya-i-otladky-shhgitov-s-svtomatikoy-na-plk#4_____io
Только я НЕ использую прямую адресацию, а разбираю в таких переменных битовые маски и именую переменные понятным текстом. Вот так:

hwBtnLgt1EPrihojMain : BOOL; (* W2.I1: Кнопки LT-41: 1 Этаж Прихожая Общий *)
hwBtnLgt1EPrihojTrackShkaf : BOOL; (* W2.I2: Кнопки LT-42: 1 Этаж Прихожая Трек у Шкафа *)
hwBtnLgt1EPrihojZerkalo : BOOL; (* W2.I3: Кнопки LT-43: 1 Этаж Прихожая Зеркало *)
hwBtnLgt1EPrihojSpotDver : BOOL; (* W2.I4: Кнопки LT-44: 1 Этаж Прихожая Споты Дверь *)
hwBtnLgt1EPrihojFuncShkaf : BOOL; (* W2.I5: Кнопки LT-45: 1 Этаж Прихожая Функциональный у Шкафа *)
hwBtnLgt1EPrihojIgrDecor : BOOL; (* W2.I6: Кнопки LT-46: 1 Этаж Прихожая/Игровая Декор *)
hwBtnLgt1EZakutok : BOOL; (* W2.I7: Кнопки LT-47: 1 Этаж Закуток *)
hwBtnLgt1EMicroKabinet : BOOL; (* W2.I8: Кнопки LT-48: 1 Этаж Микрокабинет *)
hwBtnLgt1EIgrMain : BOOL; (* W2.I9: Кнопки LT-49: 1 Этаж Игровая Общий *)
hwBtnLgt1EIgrTrack : BOOL; (* W2.I10: Кнопки LT-50: 1 Этаж Игровая Трек Окно *)


hwBtnLgt1EPrihojMain := W2_DI32.0; (* W2.I1: Кнопки LT-41: 1 Этаж Прихожая Общий *)
hwBtnLgt1EPrihojTrackShkaf := W2_DI32.1; (* W2.I2: Кнопки LT-42: 1 Этаж Прихожая Трек у Шкафа *)
hwBtnLgt1EPrihojZerkalo := W2_DI32.2; (* W2.I3: Кнопки LT-43: 1 Этаж Прихожая Зеркало *)
hwBtnLgt1EPrihojSpotDver := W2_DI32.3; (* W2.I4: Кнопки LT-44: 1 Этаж Прихожая Споты Дверь *)
hwBtnLgt1EPrihojFuncShkaf := W2_DI32.4; (* W2.I5: Кнопки LT-45: 1 Этаж Прихожая Функциональный у Шкафа *)
hwBtnLgt1EPrihojIgrDecor := W2_DI32.5; (* W2.I6: Кнопки LT-46: 1 Этаж Прихожая/Игровая Декор *)
hwBtnLgt1EZakutok := W2_DI32.6; (* W2.I7: Кнопки LT-47: 1 Этаж Закуток *)
hwBtnLgt1EMicroKabinet := W2_DI32.7; (* W2.I8: Кнопки LT-48: 1 Этаж Микрокабинет *)
hwBtnLgt1EIgrMain := W2_DI32.8; (* W2.I9: Кнопки LT-49: 1 Этаж Игровая Общий *)
hwBtnLgt1EIgrTrack := W2_DI32.9; (* W2.I10: Кнопки LT-50: 1 Этаж Игровая Трек Окно *)

Мои методы и технологии описаны в статье. Берите все на вооружение!
Там ещё и технология теестирования IO и обработки ошибок IO есть!

1exan
15.02.2024, 11:05
АБСОЛЮТНО соглаасен! Я так делаю прям вот всегда! У меня этому даже кусок статьи посвящён (рекомендую прочитать, без шуток): https://cs-cs.net/technologii-testirovaniya-i-otladky-shhgitov-s-svtomatikoy-na-plk#4_____io
Только я НЕ использую прямую адресацию, а разбираю в таких переменных битовые маски и именую переменные понятным текстом. Вот так:
[CODE]hwBtnLgt1EPrihojMain : BOOL; (* W2.I1: Кнопки LT-41: 1 Этаж Прихожая Общий *)
hwBtnLgt1EPrihojTrackShkaf : BOOL; (* W2.I2: Кнопки LT-42: 1 Этаж Прихожая Трек у Шкафа *)
hwBtnLgt1EPrihojZerkalo : BOOL; (* W2.I3: Кнопки LT-43: 1 Этаж Прихожая Зеркало *)
hwBtnLgt1EPrihojSpotDver : BOOL; (* W2.I4: Кнопки LT-44: 1 Этаж Прихожая Споты Дверь *)


А в чём смысл давать имя только байту, а потом обращаться к его битам (именованные константы, как я понял)?
Почему не именуешь сразу отдельные биты - в экселе ведь это тоже просто сделать?

Cs-Cs
15.02.2024, 11:57
А в чём смысл давать имя только байту, а потом обращаться к его битам (именованные константы, как я понял)?
Почему не именуешь сразу отдельные биты - в экселе ведь это тоже просто сделать?
Не, не именованные константы. Если не сложно - лучше почитать мою статью. Я там подробно всё расписал как раз для вставки на форум.
Шаги моей задумки такие:
1. Много переменных в программах ПЛК - булевые: Дискретные датчики, статусы сигналов, выходы на реле, контакторы.
2. Привязка переменных в ПЛК делается по разному. Встроенные входы-выходы можно привязать в конфигурации (причём одни сразу булевые, а другие - байтами по 8 входов или выходов), а IO модулей ввода-вывода вообще читается по 16 бит или по 32 бита (смотря какие модули используем0.
Всё это приводит к чёртовому зоопарку: что-то объявлено в конфигурации ПЛК, что-то используется сразу в коде типа "DIModbus.4" без понятных имён, что-то формируется ещё где-то.
3. Меня выбесило то, что нет системности, где привязываются ВСЕ каналы ввода-вывода, и я сделал так:
а) Объявляю в Глобальных переменных все нужные названия переменных ввода-вывода ПОНЯТНЫМИ именами.
б) В конфигурации ПЛК объявляю групповые переменные для каналов опроса - битовые маски.
в) В задаче (в одном месте) TaskIO разбираю битовые маски и привязываю их там к моим переменным.
г) В остальных задачах обращаюсь к своим понятным и красивым переменным.
Благодаря этому привязка IO происходит ТОЛЬКО в одном месте программы, она наглядная, и там можно что-то легко поменять.
А в программе я оперирую понятными переменными типа hwStatusUPS, hwStatusL1 и так далее, что делает код читаемым и избавляет от магических чисел (с которыми я на форуме ОВЕНа сталкиваюсь больше, чем за весь стаж программирования).

В общем, настоятельно рекомендую почитать мою статью! Заодно новых методов разработки и отладки можно там набраться!

1exan
15.02.2024, 12:53
при смене платформы же легче в новой конфигурации задать только одно имя, чем прописывать каждый бит(буль) отдельно, даже если это в эксель

Возможно, но в конечном итоге всё рано где-то придётся указывать конкретный номер бита, поэтому я большой разницы не вижу

Cs-Cs
15.02.2024, 13:54
Возможно, но в конечном итоге всё рано где-то придётся указывать конкретный номер бита, поэтому я большой разницы не вижу Пожалуйста найди час времени (за обедом, перед сном) прочитать мою статью. Тогда и обсудим.
Я готов учиться у самых лучших. Сейчас я не вижу, чему мне учиться: прямая адресация и непонятные имена переменных - это полшага до магических чисел, за которые надо наказывать!

МихаилГл
15.02.2024, 14:11
Не знаю о чем спор, но программа должна быть универсальный, даже иметь возможность переноса на железо другого производителя. А для этого программа пишется не опираясь на вид описания входов выходов. Для этого организуют прокладки, которые тэги контроллера копируют в тэги программы и наоборот.

1exan
15.02.2024, 14:17
Пожалуйста найди час времени (за обедом, перед сном) прочитать мою статью. Тогда и обсудим.
Я готов учиться у самых лучших. Сейчас я не вижу, чему мне учиться: прямая адресация и непонятные имена переменных - это полшага до магических чисел, за которые надо наказывать!

DI_5 не более непонятное имя, чем W1_DIA.0:
DI_5 - это дискретный вход №5, что по-моему, очевидно следует из его имени, и W1_DIA.0 - это тоже дискретный вход №5, что уже не совсем очевидно, и поэтому наверное дополнительно указывается в комментарии

Я лично не вижу ничего плохого в прямой адресации при работе с физическими входами/выходами

1exan
15.02.2024, 14:20
Не знаю о чем спор, но программа должна быть универсальный, даже иметь возможность переноса на железо другого производителя. А для этого программа пишется не опираясь на вид описания входов выходов. Для этого организуют прокладки, которые тэги контроллера копируют в тэги программы и наоборот.

Так все разговоры только о способе организации этой прокладки и идут

Easy_Enemy
15.02.2024, 16:56
ни чего не понял, Flap это структура, начинающаяся с REAL, как Вы присваиваете ей(конкретно реалу) байт с дискретными переменными управления на открытие и закрытие?
Прошу прощения, не правильно написал изначально, и народ запутал, уже голова не варила: заслонки трехпроводные, двухфазные, без отслеживания положения. Собственно, описанное с использованием REAL - были функции отслеживания текущего положения заслонки по времени ее работы. Еще раз - пардон


Вероятность того, что структуры ваших внутренних объектов совпадут с типами и расположением физических входов и выходов в контроллере - приближается к нулю.
Поясните, пожалуста, не вкурил.. Я создаю некую систему, пусть ту же вентиляху. Одно из свойств системы - те же заслонки. В функции карты (соответствие входов/выходов и переменных в массиве для обработки 1 блоком) собственно все раскидываю. При каких условиях может начаться апокалипсис?
Обзываю входы в конфигураторе на первых порах, для тестов, чтоб не запутаться.


Только я НЕ использую прямую адресацию, а разбираю в таких переменных битовые маски и именую переменные понятным текстом.
Вот тут как раз и случился затык, от чего и полез на форум народ пытать. Есть выход (пусть QX1.0, запихал его в переменную (Пусть DO1). Далее, для того, чтобы можно было обработать в цикле, присваиваем этот выход в переменную массива, пусть Sys[1]._Do1. Соответственно, для всей системы была написана функция карты (Sys[1]._Do1:=DO1) (делаю так для всех систем, а потом объявляю один раз при инициализиции). При управлении "без лишнего" - работает. Включается-выключается и через массив и через прямую. При управлении, как было, через CASE работает только, если мы пишем непосредственно в переменную выхода (прямую, DO1). Может я чего не понимаю, конечно.. А то и многое) В обработке через условия (CASE/IF), если запишем в переменную массива (Sys[1]._Do1), видно, что значение ее меняется, но не присваивается в D01. Поэтому и разродилась идея уйти в обычные дискретные выходы, так как нет "прослойки", в виде "DO...", а можно сразу, через адресацию сунуть все в эррей. Ну, как бэ - да, во-первых, ADR на %QX сделать не удастся, во-вторых - нужны 2 переменные (указатель на байт и указатель на бит), но, и черт с ним, не самая большая проблема.

Статью почитаю, спасибо)

1exan
15.02.2024, 18:09
...
Есть выход (пусть QX1.0, запихал его в переменную (Пусть DO1). Далее, для того, чтобы можно было обработать в цикле, присваиваем этот выход в переменную массива, пусть Sys[1]._Do1. Соответственно, для всей системы была написана функция карты (Sys[1]._Do1:=DO1)
...

Прочитал два раза, ничего не понял

Посмотрел ещё раз ваш проект:
Вы объявляете выходы в конфигурации:
73596
а потом здесь зачем то читаете их состояние


Ven[1].Flap.Open:=Flap1Open;
Ven[1].Flap.Close:=Flap1Close;



Вы ничего не путаете?

west
15.02.2024, 18:28
Прошу прощения, не правильно написал изначально, и народ запутал, уже голова не варила: заслонки трехпроводные, двухфазные, без отслеживания положения.
И сейчас неправильно!
Могу лишь догадываться, но скорее всего разговор про привод КЗР (клапан запорно-регулирующий) без датчика положения.
И раз привод трёхпроводный, то никак не "двухфазный" (это вообще в нашем бренном мире существует???).

Собственно, описанное с использованием REAL - были функции отслеживания текущего положения заслонки по времени ее работы.
а люфт заслонки и привода, время выбега, инерционный выбег и т.д. учитывали?
если нет, то уже через день весь ваш расчёт (функции отслеживания текущего положения заслонки) будет показывать это положение в попугаях.

Easy_Enemy
15.02.2024, 18:34
Прочитал два раза, ничего не понял

Посмотрел ещё раз ваш проект:
Вы объявляете выходы в конфигурации:
73596
а потом здесь зачем то читаете их состояние


Ven[1].Flap.Open:=Flap1Open;
Ven[1].Flap.Close:=Flap1Close;



Вы ничего не путаете?
Как сказал capzap - неуемный метод тыка.. Предполагалось, что, таким образом их можно засунуть (выходы) в массив. Эт уже пробовал менять местами (а вдруг..). "Вдруг" не случилось. Теперь все работает. Может не очень красиво, но работает:


Ven[3].Flap.Num := ADR(%QB3.0);

Ven[3].Flap.Num^.0 := Ven[3].Flap.Close; (* Бит 0, Заслонка 3, закрыть *)
Ven[3].Flap.Num^.1 := Ven[3].Flap.Open; (* Бит 1, Заслонка 3, открыть *)



Соответственно - Ven[3].Flap.Num : Pointer to Byte

Easy_Enemy
15.02.2024, 18:47
И сейчас неправильно!
Могу лишь догадываться, но скорее всего разговор про привод КЗР (клапан запорно-регулирующий) без датчика положения.
И раз привод трёхпроводный, то никак не "двухфазный" (это вообще в нашем бренном мире существует???).

Правильно. Изначально озвучили "по фазе на каждую сторону"



а люфт заслонки и привода, время выбега, инерционный выбег и т.д. учитывали?
если нет, то уже через день весь ваш расчёт (функции отслеживания текущего положения заслонки) будет показывать это положение в попугаях.

Уже по факту наблюдений. Сейчас основное - запустить. Подстройка - как получится, не успеваю (да и не хочу) заниматься всем, но не попишешь.. Самой регулировкой будет заниматься пид, а ему, как водится, плевать на погрешность в пару градусов, есть обратная связь в виде скорости воздушного потока. Увидим позже

1exan
15.02.2024, 18:57
Как сказал capzap - неуемный метод тыка.. Предполагалось, что, таким образом их можно засунуть (выходы) в массив. Эт уже пробовал менять местами (а вдруг..). "Вдруг" не случилось. Теперь все работает. Может не очень красиво, но работает:


Ven[3].Flap.Num := ADR(%QB3.0);

Ven[3].Flap.Num^.0 := Ven[3].Flap.Close; (* Бит 0, Заслонка 3, закрыть *)
Ven[3].Flap.Num^.1 := Ven[3].Flap.Open; (* Бит 1, Заслонка 3, открыть *)



Соответственно - Ven[3].Flap.Num : Pointer to Byte

Да надо было просто в вашем первом варианте так и написать:

Flap1Open := Ven[1].Flap.Open;
Flap1Close := Ven[1].Flap.Close;
Flap2Open := Ven[2].Flap.Open;
...

1exan
15.02.2024, 19:01
Правильно. Изначально озвучили "по фазе на каждую сторону"



Уже по факту наблюдений. Сейчас основное - запустить. Подстройка - как получится, не успеваю (да и не хочу) заниматься всем, но не попишешь.. Самой регулировкой будет заниматься пид, а ему, как водится, плевать на погрешность в пару градусов. Увидим позже

Регулятор - что с аналоговым выходом, что с дискретными открыть/закрыть - может вообще обходиться без информации о текущем положении заслонки

Easy_Enemy
15.02.2024, 19:11
Да надо было просто в вашем первом варианте так и написать:

Flap1Open := Ven[1].Flap.Open;
Flap1Close := Ven[1].Flap.Close;
Flap2Open := Ven[2].Flap.Open;
...
С этого и началась вся тема - так не работает в режиме калибровки, который состоит из нескольких шагов CASE. Вся история заканчивается тем, что видно, что происходит на каждом шаге и даже присваиваются значения в Ven[1].Flap.Open, но не в Flap1Open.
Условно


CASE step Of
1: ....
Ven[1].Flap.Open:=true;
...
...
2: ...
Ven[1].Flap.Close:=true;
...
...
END_CASE

Так не работает. Ven[1].Flap.Open / Close - меняют значения, но не пишут их в выходы.




CASE step Of
1: ....
Flap1Open:=true;
...
...
2: ...
Flap1Close:=true;
...
...
END_CASE

Так работает, но это уже не массив

Поэтому вчера перешел на побитовую адресацию



Регулятор - что с аналоговым выходом, что с дискретными открыть/закрыть - может вообще обходиться без информации о текущем положении заслонки

С положением-то проблем не было, как раз..

Easy_Enemy
15.02.2024, 19:45
Мдяяя. Чего то не работало. Был выложен фрагмент в котором куча вопросов. После оказалось что фрагмент не тот. А тот что тот - тоже не работает. Потом, снова внезапно, оказалось проблема не в том фрагменте который не выложился, а совсем в другом месте. Но в том месте тоже работает не так. Зато - маппирование, прямая адресация, глубокомысленные думки про скорость..
Но надо запустить. Как нибудь))



Отлично работает, видно включение выхода на ПЛК, видно движение в визуализации.
Вчера написал режим калибровки/антизалипания (время от времени полностью открывать, потом закрывать для синхронизации положения) и проблема, в том, что, по каким-то причинам данный функция пытается выполниться за 1 цикл ПЛК, то есть не записывает выходные переменные. Подскажите, как обыграть данную ситуёвину( Максимально упрощенный блок калибровки:



Таймеры и внутри и за CASE - работают. Работает и счетчик шагов, но не присваивались значения на выходы ПЛК..

Вопрос по сути, не по содержимому. Содержимое менялось раз 500 в попытке дойти до чего-то

Валенок
15.02.2024, 20:04
Ну да. Все отлично работает. Только не записывает. И надо дойти до чего нибудь. Чтоб записывало. А так - все хорошо. Даже 500 вариантов

МихаилГл
15.02.2024, 20:11
Думаю надо с нуля переработать код. Обычно это помогает.
Я год прорабатывал программу для управления механизмом с 32мя датчиками, всеми авариями от не сошёл с концевого до одновременно нажатых кнопок. 3 раза переделывал. Теперь только в проекты его вставляю и не задумываюсь как там что работает.

Easy_Enemy
15.02.2024, 20:21
Думаю надо с нуля переработать код. Обычно это помогает.
Я год прорабатывал программу для управления механизмом с 32мя датчиками, всеми авариями от не сошёл с концевого до одновременно нажатых кнопок. 3 раза переделывал. Теперь только в проекты его вставляю и не задумываюсь как там что работает.
По-большому счету - так и получилось. Единственное - пока так и не понял, как можно обработать быстрые дискретные выходы в массиве, но пока забью, решилось и без них.

1exan
16.02.2024, 05:17
По-большому счету - так и получилось. Единственное - пока так и не понял, как можно обработать быстрые дискретные выходы в массиве, но пока забью, решилось и без них.

Никак нельзя обработать дискретные выходы в массиве, потому что они им не являются

Валенок
17.02.2024, 12:07
Это от нежелания банально преварительно "ассоциировать" их в массив юзающих их обьектов (и забыв про какие то там физические входа) по причине это не круто/этож примитивные присвоения/это много строк. Но на фоне этого заполонить код многобуквием, спорными вопросами и непонятно зачем кучей таймеров и флагов при наличии автомата.

Vesper
17.02.2024, 16:20
Дорогие друзья помогите с программой для ПЛК 160 надо настроить опрос и прием данных китайского датчика растворенного кислорода LH-DY06 по rs485

МихаилГл
17.02.2024, 17:00
Ну первая страница вас чем не устраивает? Считываете с 200 регистра 3 регистра. Только десятичное число в ответе поделите на 100.

PS такие документы лучше не через переводчик, а хотя бы на английском...

melky
17.02.2024, 17:08
У кого под руками установленный CodeSys, скиньте код BLINK из него пожалуйста. находится в Util.lib

1exan
17.02.2024, 17:19
У кого под руками установленный CodeSys, скиньте код BLINK из него пожалуйста. находится в Util.lib



FUNCTION_BLOCK BLINK
(* Function block to simulate a turn signal *)
VAR_INPUT
ENABLE:BOOL; (* TRUE:run Blink, FALSE: OUT keeps its value*)
TIMELOW:TIME; (* Time for OUT=FALSE *)
TIMEHIGH:TIME; (* Time for OUT=TRUE *)
END_VAR
VAR_OUTPUT
OUT:BOOL; (* output variable, starting with FALSE *)
END_VAR
VAR
CLOCK:TP;
END_VAR

CLOCK; (* call Timer *)
IF CLOCK.Q=FALSE AND ENABLE THEN (* time passed or init *)
CLOCK(IN:=FALSE); (* reset Timer *)
CLOCK(IN:=TRUE); (* restart Timer *)
IF OUT=FALSE THEN
CLOCK.PT:=TIMEHIGH;
ELSE
CLOCK.PT:=TIMELOW;
END_IF;
OUT := NOT OUT; (* invert *)
END_IF

melky
17.02.2024, 17:28
1exan спасибо. А то не очень хотелось устанавливать на домашний комп, а на работу только в понедельник :)

Vesper
17.02.2024, 17:29
Ну первая страница вас чем не устраивает? Считываете с 200 регистра 3 регистра. Только десятичное число в ответе поделите на 100.

PS такие документы лучше не через переводчик, а хотя бы на английском...

А можешь поподробней расписать как это изобразить в codesys.

kondor3000
17.02.2024, 17:58
А можешь поподробней расписать как это изобразить в codesys.

Посмотрите обучающие видео №6, а лучше все 13 шт. https://www.youtube.com/watch?v=hOhLY8GVbMo&list=PL2EcVEe6E9SB4F3WVm-MptpHA5ep0nrq5&index=6

FedosovaLudmila
17.02.2024, 18:28
Подскажите, пожалуйста, почему в конфигурации LeftSide ПЛК-210-12 отсутствует параметры/настройки ABZ -энкодеров? И возможно ли их добавить? В конфигурации ПЛК-210-01 данные параметры присутствуют ( скриншоты прилагаем).

73636
73637

kondor3000
17.02.2024, 18:52
Подскажите, пожалуйста, почему в конфигурации LeftSide ПЛК-210-12 отсутствует параметры/настройки ABZ -энкодеров? И возможно ли их добавить? В конфигурации ПЛК-210-01 данные параметры присутствуют ( скриншоты прилагаем).

Вы пишите в раздел Codesys 2.3, а вопросы задаёте по Codesys 3.5 и ПЛК2хх, повнимательней.

Николай Суриков
17.02.2024, 19:07
Подскажите, пожалуйста, почему в конфигурации LeftSide ПЛК-210-12 отсутствует параметры/настройки ABZ -энкодеров? И возможно ли их добавить? В конфигурации ПЛК-210-01 данные параметры присутствуют ( скриншоты прилагаем).

73636
73637

Потому что ПЛК210-1Х не поддерживают подключение энкодеров.

Характеристики входов ПЛК210-0Х
73639

Характеристики входов ПЛК210-1Х
73640

МихаилГл
17.02.2024, 19:57
Потому что ПЛК210-1Х не поддерживают подключение энкодеров.

Характеристики входов ПЛК210-0Х
73639

Характеристики входов ПЛК210-1Х
73640

Ну можно в крайнем случае свою программу для энкодера написать. А вы так кардинально: не поддерживает. Просто нет аппаратного счётчика.

FedosovaLudmila
17.02.2024, 20:21
Всем спасибо за помощь! Будем писать сами.

FedosovaLudmila
17.02.2024, 20:27
В кратком руководстве по эксплуатации на ПЛК210-12 указано, что он поддерживает энкодеры ABZ.

73642

МихаилГл
17.02.2024, 20:38
В кратком руководстве по эксплуатации на ПЛК210-12 указано, что он поддерживает энкодеры ABZ.

73642

У меня есть такая. Для 2х входов. Но соответственно без аппаратной части будет работоспособна на небольших скоростях, ограниченных периодом программы. Могу в понедельник скинуть.

Кстати, может они забыли это в прошивку добавить и скоро будет апдейт...

FedosovaLudmila
17.02.2024, 23:13
Да, большое спасибо. Пример точно не будет лишнем.

МихаилГл
19.02.2024, 04:42
Да, большое спасибо. Пример точно не будет лишнем.

Вот попробуйте вот это:


PROGRAM POU_ENCODER
VAR
//Энкодер направления вращения
a: BOOL; //Вход датчика А
b: BOOL; //Вход датчика В
a1: BOOL; //Условие 1го положения
a2: BOOL; //Условие 2го положения
a3: BOOL; //Условие 3го положения
a4: BOOL; //Условие 4го положения
//Энкодер направления вращения
//Направление вращения
c0: BOOL; //Вращение вперед
d0: BOOL; //Вращение назад
//Направление вращения
zIMP1: R_TRIG; //Фронт импульса датчика А
zIMP2: R_TRIG; //Фронт импульса датчика В
zIMP3: F_TRIG; //Спад импульса датчика А
zIMP4: F_TRIG; //Спад импульса датчика В
zIMP5: R_TRIG; //Фронт импульса для "Вращение вперед"
zIMP6: R_TRIG; //Фронт импульса для "Вращение назад"
//Определение импульсов сигнала
i1: DINT; //Количество импульсов сигнала датчика А
i2: DINT; //Количество импульсов сигнала датчика В
iF1: DINT; //Количество накопленных импульсов сигнала датчика А для "Вращение вперед"
iF2: DINT; //Количество накопленных импульсов сигнала датчика В для "Вращение вперед"
iR1: DINT; //Количество накопленных импульсов сигнала датчика А для "Вращение назад"
iR2: DINT; //Количество накопленных импульсов сигнала датчика В для "Вращение назад"
//Определение импульсов сигнала
RESET_BIT: BOOL;
END_VAR
VAR_INPUT
iA1: BOOL; //Входной импульс основного датчика
iA2: BOOL; //Входной импульс вспомогательного датчика
END_VAR
VAR_OUTPUT
oC0: BOOL; //Направление вращения - Вперед
oD0: BOOL; //Направление вращения - Назад
oN1: DINT; //Количество импульсов датчика А
oN2: DINT; //Количество импульсов датчика В
END_VAR



//iA1 = 0/1 - Входной импульс основного датчика
a := iA1;
//iA2 = 0/1 - Входной импульс вспомогательного датчика
b := iA2;
//Энкодер направления вращения
IF a AND NOT b THEN a1 := 1; END_IF
IF a AND b THEN a2 := 1; END_IF
IF NOT a AND b THEN a3 := 1; END_IF
IF NOT a AND NOT b THEN a4 := 1; END_IF
IF a1 AND a2 AND a AND b THEN d0 := a3 := a4 := 0; c0 := 1;
ELSIF a2 AND a3 AND NOT a AND b THEN d0 := a4 := a1 := 0; c0 := 1;
ELSIF a3 AND a4 AND NOT a AND NOT b THEN d0 := a1 := a2 := 0; c0 := 1;
ELSIF a4 AND a1 AND a AND NOT b THEN d0 := a2 := a3 := 0; c0 := 1;
ELSIF a1 AND a2 AND a AND NOT b THEN c0 := a3 := a4 := 0; d0 := 1;
ELSIF a2 AND a3 AND a AND b THEN c0 := a4 := a1 := 0; d0 := 1;
ELSIF a3 AND a4 AND NOT a AND b THEN c0 := a1 := a2 := 0; d0 := 1;
ELSIF a4 AND a1 AND NOT a AND NOT b THEN c0 := a2 := a3 := 0; d0 := 1;
END_IF
//Энкодер направления вращения
//Направление вращения
oC0 := c0;
oD0 := d0;
//Направление вращения
zIMP1(CLK := a);
zIMP2(CLK := b);
zIMP3(CLK := a);
zIMP4(CLK := b);
zIMP5(CLK := c0);
zIMP6(CLK := d0);
//Определение импульсов сигнала
IF c0 AND zIMP1.Q THEN i1 := i1 + 1; END_IF
IF d0 AND zIMP3.Q THEN i1 := i1 - 1; END_IF
IF c0 AND zIMP2.Q THEN i2 := i2 + 1; END_IF
IF d0 AND zIMP4.Q THEN i2 := i2 - 1; END_IF

IF c0 AND zIMP1.Q THEN iF1 := iF1 + 1; END_IF
IF zIMP5.Q AND zIMP3.Q THEN iF1 := iF1 - 1; END_IF
IF c0 AND zIMP2.Q THEN iF2 := iF2 + 1; END_IF
IF zIMP5.Q AND zIMP4.Q THEN iF2 := iF2 - 1; END_IF

IF zIMP6.Q AND zIMP1.Q THEN iR1 := iR1 + 1; END_IF
IF d0 AND zIMP3.Q THEN iR1 := iR1 - 1; END_IF
IF zIMP6.Q AND zIMP2.Q THEN iR2 := iR2 + 1; END_IF
IF d0 AND zIMP4.Q THEN iR2 := iR2 - 1; END_IF
//Определение импульсов сигнала
//Количество импульсов
oN1 := i1;
oN2 := i2;
//Количество импульсов
IF RESET_BIT THEN
i1 := i2 := iF1 := iF2 := iR1 := iR2 := 0;
RESET_BIT := a1 := a2 := a3 := a4 := c0 := d0 := 0;
END_IF

Валенок
19.02.2024, 08:42
reset_bit - онлайн отладка руками? да и комент для него странный

МихаилГл
19.02.2024, 09:00
reset_bit - онлайн отладка руками? да и комент для него странный

Нет, это сброс накопленных счетчиков в прямую и обратную сторону.

PS Для него нет коммента...
PS2 Этот бит, кстати, можно использовать как вход Z энкодера (один оборот)

Newcomer
23.02.2024, 13:43
Добрый день

Есть ПЛК110[М02] и сенсорная панель. Связь ПЛК с панелью по Ethernet. Подключаю ПЛК к ПК по Ethernet. Запускаю на ПК CoDeSys и конфигуратор панели, т.е. 2 приложения одновременно. Загружаю проект в ПЛК и запускаю. Запускаю проект для панели на ПК в режиме онлайн эмуляции. Будет ли нормальный обмен ПЛК с обоими приложениями ПК.

Newcomer
23.02.2024, 14:40
Да
.............

Это хорошо.

Newcomer
01.03.2024, 07:03
Добрый день

Как в CoDeSys посмотреть IP адрес ПЛК ?

1exan
01.03.2024, 07:18
Добрый день

Как в CoDeSys посмотреть IP адрес ПЛК ?

Подключитесь к ПЛК через USB, откройте ПЛК браузер, найдите в списке команду PLCinfo

nnov4k
02.03.2024, 16:09
Добрый день. Подскажите пожалуйста, какие есть внутренние ограничения на переменные?
Суть проблемы - ПР200 - 2 счетчика импульсов (аналоговые входы в режиме дискретных), на значениях 256 и 8717,51 не инкрементируется, при этом если поставить большие или меньшие числа, например 255,95/300 или 89000, то всё работает.
Исходя из описания типа, у меня в запасе 38 знаков,... https://docs.owen.ru/product/programmnoe_obespechenie_owen_logic/986/83358#topic-83359
В целых меньше, но до них я тоже не досчитываю...
Сетевую переменную из расчета удалял - эффекта нет. логика деления на 100/1000 исходя из количества импульсов на 10 литров или на 1 литр, соответственно на выходе кубы.
Подскажите пожалуйста, где руки гнутся не в локтях? проект прилагаю

1exan
02.03.2024, 16:25
Добрый день. Подскажите пожалуйста, какие есть внутренние ограничения на переменные?
Суть проблемы - ПР200 - 2 счетчика импульсов (аналоговые входы в режиме дискретных), на значениях 256 и 8717,51 не инкрементируется, при этом если поставить большие или меньшие числа, например 255,95/300 или 89000, то всё работает.
Исходя из описания типа, у меня в запасе 38 знаков,... https://docs.owen.ru/product/programmnoe_obespechenie_owen_logic/986/83358#topic-83359
В целых меньше, но до них я тоже не досчитываю...
Сетевую переменную из расчета удалял - эффекта нет. логика деления на 100/1000 исходя из количества импульсов на 10 литров или на 1 литр, соответственно на выходе кубы.
Подскажите пожалуйста, где руки гнутся не в локтях? проект прилагаю

Да, штука интересная
Но может я конечно не понял суть задачи, но почему бы не считать с накоплением просто количество импульсов, а потом пересчитывать его в нужные единицы?
74024

kondor3000
02.03.2024, 16:31
Добрый день. Подскажите пожалуйста, какие есть внутренние ограничения на переменные?
Суть проблемы - ПР200 - 2 счетчика импульсов (аналоговые входы в режиме дискретных), на значениях 256 и 8717,51 не инкрементируется, при этом если поставить большие или меньшие числа, например 255,95/300 или 89000, то всё работает.
Исходя из описания типа, у меня в запасе 38 знаков,... https://docs.owen.ru/product/programmnoe_obespechenie_owen_logic/986/83358#topic-83359
В целых меньше, но до них я тоже не досчитываю...
Сетевую переменную из расчета удалял - эффекта нет. логика деления на 100/1000 исходя из количества импульсов на 10 литров или на 1 литр, соответственно на выходе кубы.
Подскажите пожалуйста, где руки гнутся не в локтях? проект прилагаю

У вас многократная конвертация, при чём в Лоджике она урезанная, из числа 256.5678, при конвертации получается 256 просто.

nnov4k
02.03.2024, 16:32
Да, штука интересная
Но может я конечно не понял суть задачи, но почему бы не считать с накоплением просто количество импульсов, а потом пересчитывать его в нужные единицы?
74024
переменная water-internal выведена на панель для возможности коррекции начального значения (условно если света не было, а был водоразбор или работал котёл) - т.е. стартовать в теории должно с энергонезависимой переменной из памяти
пробовал альтернативный вариант - верхний блок вложения, считает нормально, но вносит ошибку в 5 знак...


У вас многократная конвертация, при чём в Лоджике она урезанная, из числа 256.5678, при конвертации получается 256 просто.
благодарю за оперативный ответ,
случаем не подскажете, как это обойти? - странный наверное вопрос - но внутренние блоки же должны работать со стандартной длиной чисел? (аналогичной базовым?) - во вложенном варианте всё считается в плавающей точке и на числах больше 256002 / 1000 уже ошибка... - сейчас попробую переписать на ST

1exan
02.03.2024, 17:04
переменная water-internal выведена на панель для возможности коррекции начального значения (условно если света не было, а был водоразбор или работал котёл) - т.е. стартовать в теории должно с энергонезависимой переменной из памяти
пробовал альтернативный вариант - верхний блок вложения, считает нормально, но вносит ошибку в 5 знак...


благодарю за оперативный ответ,
случаем не подскажете, как это обойти? - странный наверное вопрос - но внутренние блоки же должны работать со стандартной длиной чисел? (аналогичной базовым?) - во вложенном варианте всё считается в плавающей точке и на числах больше 256002 / 1000 уже ошибка... - сейчас попробую переписать на ST


Есть такая штука, называется Алгоритм_Кэхэна (https://ru.wikipedia.org/wiki/Алгоритм_Кэхэна)
Если я правильно понял это, то выглядит как-то так:
74026

nnov4k
02.03.2024, 17:22
Алгоритм_Кэхэна[/URL]

спасибо за идею и реализацию, всё-таки попробую без двойных костылей на паскале ) честно говоря, не ожидал таких граблей в простых вычислениях от "промышленного" реле

1exan
02.03.2024, 17:25
спасибо за идею и реализацию, всё-таки попробую без двойных костылей на паскале ) честно говоря, не ожидал таких граблей в простых вычислениях от "промышленного" реле

Я не уверен, что это проблема конкретно OL, скорее самого способа представления чисел с плавающей запятой

kondor3000
02.03.2024, 17:37
всё-таки попробую без двойных костылей на паскале ) честно говоря, не ожидал таких граблей в простых вычислениях от "промышленного" реле

Думаю, что надо считать в целочисленном формате (32 битным счётчиком), с плавающей запятой будут проблемы больше 5 значного числа, в любом случае.
Даже по варианту Алгоритм_Кэхэна. И дело тут не в реле, а в представлении Float.

В промышленных счётчиках используют комбинированный вариант, целое до запятой и Float после запятой.

nnov4k
02.03.2024, 18:17
kondor3000, 1exan, спасибо за идеи, ушел в реализацию )
ошибка действительно вылезает в блоке fMUL, а там есть оговорка - "Если во время выполнения операции функции значение числа получается больше 4294967295 (32 бита), то биты, выходящие за разрядность 32 бита, отсекаются."
придется вычислять целую и дробную отдельно,...

kondor3000
02.03.2024, 18:49
kondor3000, 1exan, спасибо за идеи, ушел в реализацию )
ошибка действительно вылезает в блоке fMUL, а там есть оговорка - "Если во время выполнения операции функции значение числа получается больше 4294967295 (32 бита), то биты, выходящие за разрядность 32 бита, отсекаются."
придется вычислять целую и дробную отдельно,...

У меня получилось так 74028

nnov4k
02.03.2024, 21:43
kondor3000, спасибо, красивое решение!
пока закину счетчиком в целых (на панели будет основная - как и было в кубах = счетчик, для ввода = в литрах) - за то простопросто )))

nnov4k
03.03.2024, 09:31
накой вообще чего-то делить перед отправкой в сеть?
чтоб была нормальная размерность (=счетчику) и дальше её не пересчитывать

nnov4k
03.03.2024, 11:34
Вы уже споткнулись о машинный ноль. Зачем терять точность при передаче?
она мне не нужна - чтоб базу не засорять я забираю её модбасом один раз в час и строю почасовой лог потребления воды, газа, электричества (это "домашняя" автоматизация, на работе да - каждое изменение по МЭК 104 с дискретом 0,1% ДИ с хранением в 3 года с десятков тысяч приборов)
в ситуации с, считаю, запланированной ущербностью математики, закрепленной оговоркой в РЭ в целях загнать всех с ПР на ПЛК, я ошибался с точностью и у меня не сходились, условно, накопительные итоги - Вы правы, это критически важно и потребовало внесения изменений в алгоритм для корректной обработки в рамках МОИХ диапазонов измерений, а сейчас накопления считаются точно, могу получить ошибку исключительно при снятии показания в 5м знаке при разрядности эталонного счетчика в 3 знака после запятой, при этом не накапливая ошибку... в общем то не принципиально :)

IVM
05.03.2024, 17:44
Что не так в строке ?

IVM
05.03.2024, 18:13
SI32 небось Di ?

Нашел ошибку. Должно быть SI33 := WORD_IN1.0; а не SI32 := WORD_IN1.0;

IVM
05.03.2024, 18:53
Отлично!
Ну а SI32 был Di ?

Да, был.------

Токарь
06.03.2024, 02:19
Форумчане, всем доброго времени суток.
Практически мой первый проект в codesys, хочу +- реализовать считывание энкодера из видеоуроков:

https://www.youtube.com/watch?v=8jU-CjICKn8

https://www.youtube.com/watch?v=no9roseNvLw

Короткая программа, вызываемая циклическим таймером 20мкс и основная программа с вызовом подпрограммы.

Проблема: при попытке скомпилировать проект выдаёт ошибки "3700 ANALYZEEXPRESSION (1): POU с именем ANALYZEEXPRESSION уже включен в библиотеку "Analization.lib" и вторую похожую, скрин:

74116

Если удалить библиотеку Analization.lib то выскакивает ошибка:

74117

Аналогичный эффект, если удалить библиотеку Analizationnew.lib Может быть кто-то подскажет, в чём засада?

kondor3000
06.03.2024, 08:14
Форумчане, всем доброго времени суток.
Практически мой первый проект в codesys, хочу +- реализовать считывание энкодера из видеоуроков:
Проблема: при попытке скомпилировать проект выдаёт ошибки "3700 ANALYZEEXPRESSION (1): POU с именем ANALYZEEXPRESSION уже включен в библиотеку "Analization.lib" и вторую похожую, скрин:
Аналогичный эффект, если удалить библиотеку Analizationnew.lib Может быть кто-то подскажет, в чём засада?

Написано же, нет библиотеки SisLibCallBack, её надо добавить.
В таких случаях проще проект было выложить.

Токарь
06.03.2024, 11:10
Написано же, нет библиотеки SisLibCallBack, её надо добавить.


Большое спасибо, помогло. Я просто думал, что основные библиотеки уже "там".

olegik7711
09.03.2024, 15:35
Здравствуйте! Помогите разобраться. Есть программа с визуализацией в среде CoDeSys 2.3. Панельный компьютер с Windows. Подскажите пожалуйста:
1) Что нужно , чтобы при запуске ПЛК на экране компьютера (во весь экран), появлялась визуализация и ничего больше. То есть чтобы оператор не имел доступа к коду. Может нужно купить лицензию CoDeSys HMI или есть еще какие-то пути?
2) Можно ли значения переменных проекта CoDeSys 2.3 передавать (или архивировать) в Exel? В конечном счете нужен отчет в Exel или PDF c трендом.

kondor3000
09.03.2024, 17:24
Здравствуйте! Помогите разобраться. Есть программа с визуализацией в среде CoDeSys 2.3. Панельный компьютер с Windows. Подскажите пожалуйста:
1) Что нужно , чтобы при запуске ПЛК на экране компьютера (во весь экран), появлялась визуализация и ничего больше. То есть чтобы оператор не имел доступа к коду. Может нужно купить лицензию CoDeSys HMI или есть еще какие-то пути?
2) Можно ли значения переменных проекта CoDeSys 2.3 передавать (или архивировать) в Exel? В конечном счете нужен отчет в Exel или PDF c трендом.

А на каком ПЛК всё работает?
Если это виртуальный PLC WinNT 2.4, то есть ограничение по времени 2 часа, придётся периодически перезапускать.
Во всю ширину раздвинуть нельзя, всё равно рамки останутся, даже если сделать пароль на запись, всё равно оператор сможет залезть куда не надо (хотя изменить ничего не сможет).
Для архивации на флешку, нужен реальный контроллер, версии M 02 (v.2). А лучше, панель оператора, типа СП3хх, тогда уже и залезть никуда не возможно будет.

По поводу лицензии не подскажу, никогда не имел такой потребности.
А пока лучший вариант конвертировать на 3.5 и сделать проект для СПК1хх, при запуске визуализация на весь экран будет, хотя и оттуда можно выйти при желании.

IVM
10.03.2024, 12:25
Здравствуйте! Помогите разобраться. Есть программа с визуализацией в среде CoDeSys 2.3. Панельный компьютер с Windows. Подскажите пожалуйста:
1) Что нужно , чтобы при запуске ПЛК на экране компьютера (во весь экран), появлялась визуализация и ничего больше. То есть чтобы оператор не имел доступа к коду. Может нужно купить лицензию CoDeSys HMI или есть еще какие-то пути.

Нужна лицензия. Она раньше 200 евро стоила.

дрю
12.03.2024, 11:24
Добрый день! Панель СП310 мастер - ПЛК110 слейв. Необходимо организовать регулируемую временую задержку включения механизма. Задержка будет формироваться в панели в энергонезависмой памяти. Предполагю в ПЛК это стандартный таймер ТОН. Вопрос какой тип данных и регистра необходимо указать в панеле чтобы он состыковался с входам таймера PT (на нем должен быть тип данных TIME). Спасибо

1exan
12.03.2024, 11:31
Добрый день! Панель СП310 мастер - ПЛК110 слейв. Необходимо организовать регулируемую временую задержку включения механизма. Задержка будет формироваться в панели в энергонезависмой памяти. Предполагю в ПЛК это стандартный таймер ТОН. Вопрос какой тип данных и регистра необходимо указать в панеле чтобы он состыковался с входам таймера PT (на нем должен быть тип данных TIME). Спасибо

Тип данных в панели будет зависеть от планируемого диапазона значений задержки и требуемой дискретности её задания.
А TIME - это просто время в миллисекундах, в ПЛК можно любой тип данных пересчитать в TIME

дрю
12.03.2024, 11:39
Если работать с секундами в панели (диапозон 0-10)Вот такие настройки в панеле Правильны?7427274273

МихаилГл
12.03.2024, 11:39
Добрый день! Панель СП310 мастер - ПЛК110 слейв. Необходимо организовать регулируемую временую задержку включения механизма. Задержка будет формироваться в панели в энергонезависмой памяти. Предполагю в ПЛК это стандартный таймер ТОН. Вопрос какой тип данных и регистра необходимо указать в панеле чтобы он состыковался с входам таймера PT (на нем должен быть тип данных TIME). Спасибо

В панели делайте X - word, а в ПЛК Y:= word_to_time(X) - получите миллисекунды. Если надо больше: Y:= to_time(X * 1000) - это секунды...

МихаилГл
12.03.2024, 11:40
Если работать с секундами в панели (диапозон 0-10)Вот такие настройки в панеле Правильны?7427274273

Правильные. Только это будут миллисекунды при конвертации to_time

дрю
12.03.2024, 11:43
Спасибо буду пробовать

дрю
12.03.2024, 12:39
Все заработало.Спасибо:)

дрю
13.03.2024, 08:47
Добрый день! Подскажите пожалуста. Панель оператора СП310 мастер --ПЛК110 слейв. Как правильней организовать подключение модулей ввода-вывода используя слейв на том же канале RS_485-1 или использовать Другой RS_485-2 но в данном случаи ПЛК уже выступает мастером сети?

МихаилГл
13.03.2024, 09:07
Добрый день! Подскажите пожалуста. Панель оператора СП310 мастер --ПЛК110 слейв. Как правильней организовать подключение модулей ввода-вывода используя слейв на том же канале RS_485-1 или использовать Другой RS_485-2 но в данном случаи ПЛК уже выступает мастером сети?

На другом. 2х мастеров нельзя в одной линии 485, только в TCP такое можно.

дрю
13.03.2024, 09:13
Понял,спасибо!

In_Da_Cher_A
13.03.2024, 10:58
Добрый день! Подскажите пожалуста. Панель оператора СП310 мастер --ПЛК110 слейв. Как правильней организовать подключение модулей ввода-вывода используя слейв на том же канале RS_485-1 или использовать Другой RS_485-2 но в данном случаи ПЛК уже выступает мастером сети?ПЛК-RS1 мастер - Модули Слейв
ПЛК -RS2 Слейв - СП Мастер.
Но лучше панель включать по ТСР через коммутатор, RS запасной всегда пригодится какую-нибудь приблуду по модбасу подтянуть, не смешивая с обменом по модулям

EFrol
13.03.2024, 11:09
ПЛК-110 и СП3хх еще имеют RS-232.

markeviche
19.03.2024, 16:07
Добрый день, коллеги! Подскажите плиз новичку, только знакомлюсь CoDeSys. Цепь контакт и обмотка - запускаю эмуляцию - контакт ставлю истина, обмотка остаётся всё равно ложь. Значение же на обмотке должно изменится следом за контактом. Что делаю не так? Что может быть необходимо изменить в настройках? Голову уже сломал и гугл ничего не выдаёт, неужели я один такой)))74497

In_Da_Cher_A
19.03.2024, 16:16
нажмите F5

kondor3000
19.03.2024, 16:28
Добрый день, коллеги! Подскажите плиз новичку, только знакомлюсь CoDeSys. Цепь контакт и обмотка - запускаю эмуляцию - контакт ставлю истина, обмотка остаётся всё равно ложь. Значение же на обмотке должно изменится следом за контактом. Что делаю не так? Что может быть необходимо изменить в настройках? Голову уже сломал и гугл ничего не выдаёт, неужели я один такой)))74497

Надо нажать старт программы или F5
Советую посмотреть обучающие видео на ю-туб, их полно для ПЛК Овен и панелей
https://www.youtube.com/watch?v=eSTmoNeLa7A&t=5s

markeviche
19.03.2024, 18:41
Всё работает. Надо учить матчасть)) Спасибо большое.

Nikolay.L
22.03.2024, 10:28
В комментариях к ролику https://www.youtube.com/watch?v=PdVcPaqkRLQ&t=2s
я задал вопрос: Почему в CFC вместо использования блока MOVE с EN/ENO не сделают присвоение напрямую в элементе вывода? По мне так было бы логичнее и занимало бы меньше места.
и получил ответ: Это поддержано еще начиная с очень старых версий CODESYS.

Может я что то не так понял или мы о разных вещах: 74592

kondor3000
22.03.2024, 10:36
В комментариях к ролику https://www.youtube.com/watch?v=PdVcPaqkRLQ&t=2s
я задал вопрос: Почему в CFC вместо использования блока MOVE с EN/ENO не сделают присвоение напрямую в элементе вывода? По мне так было бы логичнее и занимало бы меньше места.
и получил ответ: Это поддержано еще начиная с очень старых версий CODESYS.

Может я что то не так понял или мы о разных вещах: 74592

Присвоение через блок MOVE с EN/ENO (присвоение по условию), может быть однократным, например через R_TRIG, которое если надо, можно потом изменить (например однократная инициализация при включении или присвоение на определённом шаге, для последующего изменения).
Присвоение напрямую (просто присвоение), даже если вы потом попытаетесь изменить выходную переменную, в следующем цикле может вернуть число назад.
Так что это не однозначные решения. Всё зависит от того, что вам надо сделать.

Nikolay.L
22.03.2024, 11:48
в моем понимании это должно работать одинаково: при входе True идет присваивание, при False - нет.

Игорь Владиславович
23.03.2024, 12:08
Вопрос по графику. Для визуализации изменения параметра в виде графика создал ТРЕНД. Все получилось и в режиме эмуляции график ожил. Три кривых двигаются. После создания аналогичного графика в другом ТРЕНДЕ, случилась Ошибка 3740: Неизвестный тип ARRAY [0..3200] OF STTrend.
После откатов к состоянию, когда все работало, ошибка прилепилась. А ведь мне нужно визуализировать десяток регуляторов.

kondor3000
23.03.2024, 19:04
Вопрос по графику. Для визуализации изменения параметра в виде графика создал ТРЕНД. Все получилось и в режиме эмуляции график ожил. Три кривых двигаются. После создания аналогичного графика в другом ТРЕНДЕ, случилась Ошибка 3740: Неизвестный тип ARRAY [0..3200] OF STTrend.
После откатов к состоянию, когда все работало, ошибка прилепилась. А ведь мне нужно визуализировать десяток регуляторов.

Выложите проект и напишите какой у вас ПЛК.

Лосев Олег
24.03.2024, 11:40
Прошу совета спецов.
Есть два датчика температуры и нужно контролировать разность между ними в пределах 6 градусов.
Я накидал схемку но что то мне подсказывает что это сырая заготовка и есть более правильное решение.74649

kondor3000
24.03.2024, 11:58
Прошу совета спецов.
Есть два датчика температуры и нужно контролировать разность между ними в пределах 6 градусов.
Я накидал схемку но что то мне подсказывает что это сырая заготовка и есть более правильное решение.74649

Зачем лишние преобразования, просто сравните разницу с 6 градусами74651 Функция ABS, для отрицательной разницы -6 градусов( можно убрать)
В примере сравнил с 5 градусами.

Лосев Олег
24.03.2024, 13:31
Спасибо - это как то понятнее смотрится.

west
24.03.2024, 16:45
Есть два датчика температуры и нужно контролировать разность между ними в пределах 6 градусов.
Не особо понятно задание, но можно и так:

Лосев Олег
24.03.2024, 19:15
Да, нужно при увеличении 5 - 6 градусов разницы между двумя датчиками срабатывал выход .
Основная задача не допускать разницу более 5 - 6 градусов

ВладОвен
26.03.2024, 18:51
Здравствуйте.
Подскажите, библиотека OwenCommunication может передавать данные кириллицей при отправке данных на сервер? Т.е. работать с типом данных wstring?

Cs-Cs
26.03.2024, 21:07
Здравствуйте.
Подскажите, библиотека OwenCommunication может передавать данные кириллицей при отправке данных на сервер? Т.е. работать с типом данных wstring? Она просто передаёт БАЙТЫ. А вот что эти байты будут значит - за это она не отвечает. То есть, если ей дать указатель на wstring и указать его размер в БАЙТАХ (не в символах) - то передат этот кусок байт на сервер. Если сервер этот кусок байт поймёт как unicode-строку - то всё ОК.

Игорь Владиславович
27.03.2024, 08:58
ПЛК160 (М2)
Но у меня проект только в проекте, пока самого контроллера нет, и пробую отладить в режиме симуляции.

kondor3000
27.03.2024, 09:39
ПЛК160 (М2)
Но у меня проект только в проекте, пока самого контроллера нет, и пробую отладить в режиме симуляции.

К сожалению на новых ПЛК [M02] (V.2) тренды не поддерживаются, у вас в проекте ошибка тренда, если его удалить, то нет ошибок.
Подобная тема уже была, где то зимой, у меня на старом ПЛК тренды работают, у человека на новом ПЛК нет.
Если вам будет нужен тренд, то выводите на панели, типа СП3хх или СПК1хх

И ещё у вас 2 раза и 4 раза написаны одинаковые программы, Лучше было сделать 2 ФБ и запустить его 2 и 4 раза
А в визуализации 5 параметров Ksm %s не правильно выведены переменные. 5 предупреждений.

Игорь Владиславович
27.03.2024, 10:33
Спасибо.
А есть таргет файлы для СП3...?
Я хочу попробовать вариант с ПЛК210. Поставил CODESYS 3.5.17.30. А там будут работать тренды в симуляции? Спрашиваю, чтобы зря не тратить время.

kondor3000
27.03.2024, 10:46
Спасибо.
А есть таргет файлы для СП3...?
Я хочу попробовать вариант с ПЛК210. Поставил CODESYS 3.5.17.30. А там будут работать тренды в симуляции? Спрашиваю, чтобы зря не тратить время.

Для СПзхх таргеты не нужны, там вы сами назначаете нужные переменные, если не сталкивались, на ю-туб есть обучающие видео, панель мастер и слейв.
Видео 7 и 8 https://www.youtube.com/watch?v=yJkwRU33I80&t=0s
Для ПЛК210 и CODESYS 3.5.17.30 с трендами тоже не всё просто, работать будут, но корректно лучше через биб-ку Овен. Там Евгений Кислов вам подскажет.

Newcomer
09.04.2024, 15:45
Добрый день

Можно ли сделать так что бы по условию отрабатывались не все элементы FB, например 1 и 2 отрабатывались, а 3 нет.

МихаилГл
09.04.2024, 15:48
Добрый день

Это вопрос или ответ?

PS Переходите на st и вводите условие if.
На этом языке вы замучаетесь. Либо есть более продвинутый со входом en...

kondor3000
09.04.2024, 15:56
Добрый день

Можно ли сделать так что бы по условию отрабатывались не все элементы FB, например 1 и 2 отрабатывались, а 3 нет.

Выкиньте этот FBD в топку, пишите на CFC (или на ST), добавляете En/Eno, и управляйте элементом.

capzap
09.04.2024, 16:00
Добрый день

Можно ли сделать так что бы по условию отрабатывались не все элементы FB, например 1 и 2 отрабатывались, а 3 нет.

goto и метки ни куда не делись же

Newcomer
09.04.2024, 16:36
goto и метки ни куда не делись же

Вот этот ответ мне нравится. Пойду читать книгу легендарного Игоря Петрова.

Newcomer
09.04.2024, 16:41
Выкиньте этот FBD в топку, пишите на CFC (или на ST), добавляете En/Eno, и управляйте элементом.

У меня проект сделан на ST и FBD и выкидывать я ничего не собираюсь.

МихаилГл
09.04.2024, 16:47
У меня проект сделан на ST и FBD и выкидывать я ничего не собираюсь.

Только учтите, что go to давно не рекомендуют к использованию в других языках программирования...

Newcomer
09.04.2024, 16:49
Вот она палочка-выручалочка, которая спасет созданное непосильным трудом. ;) Спасибо, capzap.

Newcomer
09.04.2024, 17:39
Оператор LT позволяет сделать переход на нужную цепь диаграммы.

Newcomer
09.04.2024, 17:57
Только учтите, что go to давно не рекомендуют к использованию в других языках программирования...

Не тот случай.

Aera2021
12.04.2024, 09:05
Добрый день. Как реализовать в ПЛК110 реализовать запись и дальнейшее считывание переменных в память через указатели? Данные с трех ТРМ10 будут считываться каждые 10 минут на протяжении недели и один раз считываться, это большой объем данных и в ОЗУ не влезет.

kondor3000
12.04.2024, 09:26
Добрый день. Как реализовать в ПЛК110 реализовать запись и дальнейшее считывание переменных в память через указатели? Данные с трех ТРМ10 будут считываться каждые 10 минут на протяжении недели и один раз считываться, это большой объем данных и в ОЗУ не влезет.

В ПЛК110 ОЗУ - 128 Кбайт, ваших данных у меня получилось чуть больше 24 Кбайт, вполне влезет.
Только хранить данные в ОЗУ за целую неделю, думаю не правильно.
Лучше сделать запись на флешку, а ещё лучше писать в ПЗУ панели типа СП3хх, данные не потеряете и считать всегда можно и на флешку скинуть. К тому же хранить можно не неделю, а месяц или несколько месяцев.

Cs-Cs
12.04.2024, 09:28
Добрый день. Как реализовать в ПЛК110 реализовать запись и дальнейшее считывание переменных в память через указатели? Данные с трех ТРМ10 будут считываться каждые 10 минут на протяжении недели и один раз считываться, это большой объем данных и в ОЗУ не влезет. Ой! Но... указатели указывают на данные в ОЗУ. То есть, данные в ОЗУ всё равно ДОЛЖНЫ быть и БУДУТ. Указатели не позволят уменьшить занимаемую память.

In_Da_Cher_A
12.04.2024, 09:29
я может чего-то не понял
реализовать запись и дальнейшее считывание переменных в память через указатели? а чем указатели помогут вам сделать то, что вам хочется?
и если вы сами пишете, что
это большой объем данных и в ОЗУ не влезет.то веротяно
Как реализовать в ПЛК110ответ - никак

pkl
18.04.2024, 10:55
Добрый день. Ткните пжлста, где почитать про адресацию байтов по МОДБАС в ПЛК 110. Имею панель СП300 и битовая кнопка. Адрес тэга в ПЛК AT%IX7.195.0.
Как вычислить адрес для панели? Весь мозг сломал.

kondor3000
18.04.2024, 10:58
Добрый день. Ткните пжлста, где почитать про адресацию байтов по МОДБАС в ПЛК 110. Имею панель СП300 и битовая кнопка. Адрес тэга в ПЛК AT%IX7.195.0.
Как вычислить адрес для панели? Весь мозг сломал.

Адреса считаются не по этим AT%IX7.195.0, а по номеру от начала слейва, начинается с 0, если сами не можете выложите скрин.

А вообще совет, делайте 8Bit в начале сколько надо, считать с 0 биты легче. (добавлять 8Bit надо по 2 штуки, что бы занять регистр полностью).
А ещё лучше передавайте регистрами, по 16 бит, считать вообще не надо.

pkl
18.04.2024, 11:10
Непонятно, но здорово. Короче 0x и 1x при работе с ПЛК лучше не использовать. Хрен разберёшься. Будем использовать регистры.

petera
18.04.2024, 11:30
Непонятно, но здорово. Короче 0x и 1x при работе с ПЛК лучше не использовать. Хрен разберёшься. Будем использовать регистры.

Чего здесь не понятного?
https://owen.ru/forum/attachment.php?attachmentid=12345&d=1395648726

ЗЫ.
Байты (0х, 1х) находятся в той же области память, что и регистры (4х, 3х).
Т.е. в ПЛК в слейве может быть регистр, например 4х0, к битам которого из панели можно обратиться как к 0х00..0х15

МихаилГл
18.04.2024, 11:32
Непонятно, но здорово. Короче 0x и 1x при работе с ПЛК лучше не использовать. Хрен разберёшься. Будем использовать регистры.

Маленько не так. Просто карта регистров при использовании только вордов нормально будет работать, а при использовании недовордов из 8 бит недостающие 8 бит система зарезервирует своими...

pkl
18.04.2024, 11:45
И какой адрес указать для индикатора?

МихаилГл
18.04.2024, 12:09
Сначала всю таблицу регистров составьте, с разбивкой Форда на биты.

petera
18.04.2024, 12:16
И какой адрес указать для индикатора?

Нужно видеть все регистры слейва, т.к. адреса начинаются с первого регистра слейва(адрес 0)
Например75263

pkl
18.04.2024, 13:06
Их там 194.:( Сделал в формате 4х. Так проще оказалось. Проект не мой. Заранее спланировать битовые области не получилось. Поэтому и проблемы.И с Кодесис только первые шаги.
Всем спасибо за ответы. Вопрос закрыт.

In_Da_Cher_A
18.04.2024, 15:30
И какой адрес указать для индикатора?руками посчитать, если не умеете в биты и регистры

Cs-Cs
18.04.2024, 16:12
Я составлял таблички и расписывал в них биты и регистры. Вот тут писал: https://owen.ru/forum/showthread.php?t=38622&p=420631&viewfull=1#post420631

pkl
18.04.2024, 16:44
Умею и биты и регистры. Идиотская адресацию просто в Кодесис. Проще сделать 4х

Валенок
19.04.2024, 21:06
Умею и биты и регистры.
Не умеешь раз это спрашиваешь:

..Как вычислить адрес для панели? ..

И да. Тут ленивые кодеры а не лошади.
Вычислить 8( ? Считаете ?! Сами !!???

Идиотская адресацию просто в Кодесис.
дурная голова ...

pkl
20.04.2024, 16:01
Я помощи просил, а не пи... ми с тобой меряться. Не хочешь помочь, иди мимо. Или руки зудят?

МихаилГл
20.04.2024, 16:36
Я помощи просил, а не пи... ми с тобой меряться. Не хочешь помочь, иди мимо. Или руки зудят?

А вы внимательно предыдущий комментарий читали... Там вроде предложено решение вашей проблемы в наглядном виде... И это вы не считаете помощью.

Валенок
20.04.2024, 16:43
Я помощи просил, а не пи... ми с тобой меряться. Не хочешь помочь, иди мимо. Или руки зудят?
О-о! Господин ничего нечитамши, зато адресация идиотская? Господин умемши биты/регистры, но спрашивающий как посчитать номер бита?
Продолжайте чесать руки и составлять таблички))

pkl
20.04.2024, 17:21
Все что нужно почитамши. И еще почитаю. Широко шагаешь товаришь, штаны не порви.

Валенок
20.04.2024, 17:43
Все что нужно почитамши. И еще почитаю. Широко шагаешь товаришь, штаны не порви
Уже почитамши? Молодец. Адресация до сих пор идиотская?

-
Я не шагаю. Я сижу и пью темное. А штаны (как и задницу) рвать - мне не проблема если нужно.
А ты, как я понял, с белыми рученьками?

dkhokhlov
24.04.2024, 15:07
Добрый день.
Пытаюсь связаться с МК210-302 по Modbus TCP.
Честно, никогда раньше не имел дела ни с Modbus ни с OWEN.
Отправляю на сокет с указанным в конфигураторе IP такой пакет
#pragma pack(push, 1)
struct data_t {
uint16_t transaction_n;
uint16_t protocol_id;
uint16_t packet_size;

uint8_t slave_id;
uint8_t func_id;
uint16_t registry_n;
uint16_t registers_count;
uint8_t value_size;
uint8_t value;
};
#pragma pack(pop)

data_t data;
data.transaction_n = 0;
data.protocol_id = 0;
data.packet_size = 8;
data.slave_id = 1;
data.func_id = 16;
data.registry_n = 470;
data.registers_count = 1;
data.value_size = 1;
data.value = 8;

нужные значения дискретных выходов не устанавливаются.
правильный ли я пакет отправляю?

dkhokhlov
24.04.2024, 15:16
всё, получилось, прошу прощение за беспокойство

dkhokhlov
24.04.2024, 15:25
НО. Появился другой вопрос. Чтобы стабильно установить эти данные, приходится посылать одно и тоже 2 раза.
Это явно нехорошо. Что я делаю неправильно может нужна какая-то инициализация?

dkhokhlov
24.04.2024, 16:02
вернее наоборот, опытном путем выяснил, что НЕ проходит именно последняя команда. Причем дело явно не в клиенте (мастере), поскольку если отправить эту же структуру в конце, забитую 0-ми, то ничего не поменяется, сервер его просто не обработает, как и последнюю значащую команду.

kondor3000
24.04.2024, 16:04
НО. Появился другой вопрос. Чтобы стабильно установить эти данные, приходится посылать одно и тоже 2 раза.
Это явно нехорошо. Что я делаю неправильно может нужна какая-то инициализация?

Поставьте себе например Owen OPC Server, это пара минут, он может читать и записывать по Модбас или TCP, например ваш модуль.

В журнале, в логах опроса видно всё, запросы мастера, ответы модуля слейва, посмотрите как это работает.
https://owen.ru/catalog/opc_serveri

dkhokhlov
24.04.2024, 19:41
спасибо, обязательно попробую