Просмотр полной версии : Проблема с кодом на ST. Цикл выполняется с ошибкой.
Коллеги, выручайте.
Вот объявление переменных:
PROGRAM PLC_PRG
VAR
Inic: BOOL;
v2: INT;
v3: INT;
sw: BOOL;
END_VAR
VAR RETAIN
v1: INT := 20;
END_VAR
Вот сама программа (проект прилагаю):
IF NOT Inic THEN
v2 := v1;
v3 := v1;
END_IF
IF (v2 <> v1) AND sw THEN
v1 := v2;
v3 := v2;
ELSIF (v3 <> v1) AND NOT sw THEN
v1 := v3;
v2 := v3;
END_IF
sw := NOT sw;
Inic := TRUE;
Конец программы
Мне нужно, чтобы при запуске значение из памяти v1, присвоилось к v2 и v3.
Далее v1 по замыслу работает как буфер и хранение последнего значения.
Потом я меняю значение v2 или v3 и всё прекрасно синхронизируется (v1=v2=v3).
Потом я пробую менять вторую переменную v3 или v2. Тут и начинается проблема. v1 присваивает поочерёдно разные значения v2 и v3.
PS: sw добавил от отчаянья. Что с ним, что без - одно и тоже.
Вот этот кусок лучше переписать по другому:
IF Inic = FALSE THEN
v2 := v1;
v3 := v1;
Inic := TRUE;
END_IF
То есть сразу ставим флаг инициализации в коде инициализации, а не где-то там в конце программы.
Дальше я бы переписал чуток по другому:
а) Хранил бы предыдущие значения для v2 и v3, обновляя их в самом конце программы:
v2Prev := v2;
v3Prev := v3;
б) Тебе же значения надо обновлять при изменении v2 или v3.
Значит я бы так и писал отдельно для каждой ветки:
IF (v2Prev <> v2) AND (можно вписать какие-то условия на валидность v2, если надо - мало ли, она не может ещё и меньше "-1" быть) THEN
v1 := v2;
END_IF
и так далее. Я могу ошибаться и тупить. Если неверно понял - прошу прощения.
Коллеги, выручайте.
Мне нужно, чтобы при запуске значение из памяти v1, присвоилось к v2 и v3.
Далее v1 по замыслу работает как буфер и хранение последнего значения.
Потом я меняю значение v2 или v3 и всё прекрасно синхронизируется (v1=v2=v3).
Потом я пробую менять вторую переменную v3 или v2. Тут и начинается проблема. v1 присваивает поочерёдно разные значения v2 и v3.
не должно быть проблем
Спасибо за пример.
Запустил проверяю. Когда работает DEMO значения записываются и всё пашет синхронно.
Если я меняю значение v2 кликнув по ней и записав новое значение, то запись происходит и всё успешно синхронизируется.
Затем я меняю значение v3 и тут проблема снова появляется, v1 присваивает новое значение v3, а потом прежнее значение v2 и так по кругу.
Я уже думаю, что это просто способ отладки такой корявый.
Объясню подробнее зачем мне это, может это вообще не так решается.
Есть v1, она в RETAIN с начальным значением. Её я храню в контроллере и выгружаю в v2 и в v3 при запуске.
v2 добавлена в порт rs232 и общается с панелью СП307.
v3 добавлена в Ethernet и работает со СКАДОЙ.
Нужно чтобы изменения на панели, загружались в СКАДУ и наоборот.
В примере проекта я объявлял переменные локально в программе.
На реальном проекте я v2 и v3 добавляю в конфигураторе добавляя Modbus slave под RS232 и ещё один Modbus slave Ethernet.
Тип подэлемента 2 byte.
keysansa
09.04.2022, 12:30
Я не понимаю, зачем тут v3.
Она всегда будет равна v2, при изменении v1.
Если вам нужен контроль однократного изменения v1, то это одно.
Если нужен контроль двухкратного изменения v1, то это другое.
keysansa
09.04.2022, 12:35
Объясню подробнее зачем мне это, может это вообще не так решается.
Есть v1, она в RETAIN с начальным значением. Её я храню в контроллере и выгружаю в v2 и в v3 при запуске.
v2 добавлена в порт rs232 и общается с панелью СП307.
v3 добавлена в Ethernet и работает со СКАДОЙ.
Нужно чтобы изменения на панели, загружались в СКАДУ и наоборот.
У вас есть контроллер, который управляется панелью и скадой. Так?
Если прав, тут надо разделить "задания" и "состояния".
Например
btnPalel: BOOL; // кнопка на панели
btnSCADA: BOOL; // кнопка в скаде
outRelay:= btnPanel OR btnSCADA;
В панели записываете переменную btnPanel, читаете переменную outRelay.
в SCADA записываете переменную btnSCADA, читаете переменную outRelay.
Например
btnPalel: BOOL; // кнопка на панели
btnSCADA: BOOL; // кнопка в скаде
outRelay:= btnPanel OR btnSCADA;
В панели записываете переменную btnPanel, читаете переменную outRelay.
в SCADA записываете переменную btnSCADA, читаете переменную outRelay.
Так я смогу включать из панели или скады.
А если эта как в моём примере уставка температуры, как быть?
А даже если эта кнопка, мне нужно чтобы я включил переключатель на панели, а выключил в скаде, но подойдя к скаде я хочу видеть переключатель включенным и выключать именно этот переключатель. Т.е. выключив в скаде, выключиться переключатель должен и на панели.
keysansa
09.04.2022, 13:27
Так я смогу включать из панели или скады.
А если эта как в моём примере уставка температуры, как быть?
Прошу прощения, не сразу вник в вашу проблему.
В вашем случае, принято использовать технологию, разработанную около века назад (https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D0%BC%D0%B0%D1%84%D0%BE%D1%80_(%D0%B6 %D0%B5%D0%BB%D0%B5%D0%B7%D0%BD%D0%B0%D1%8F_%D0%B4% D0%BE%D1%80%D0%BE%D0%B3%D0%B0)).
Используется бит, который в True означает, что значение можно изменять, в False - что изменение запрещено.
1. По старту контроллера, через некоторое время взводится бит, для защиты значения v1 от изменений по загрузке.
2. Далее, при v1<>v2, этот бит сбрасывается при операции v1=v2, на то же (или другое) время.
4. При v1<>v3 - ждем, установленного бита. И снова его сбрасываем, при выполнении v1=v3. Восстанавливаем через временной промежуток.
Это применяется, если PERSISTENT переменные хранятся в контроллере, а не в панели/SCADA.
Хотя я лично, придерживаюсь логики хранения PERSISTENT в панели/SCADA, но согласен, это не всегда эффективно.
hardkp Хммм! Вот знаешь ЧТО?! Надо тогда задачу ставить понятнее! А не "там три переменных, надо хранить последнее значение и менять если другие меняются"
Тогда ты вообще неверно делаешь прям в корне!
У меня стояла задача такая:
* Есть устройство, на котором есть местное управление (термостат) кнопками (вкл-выкл, уставка температуры)
* Есть сенсорный ПЛК (читай - панель оператора), на котором тоже нужно этим же устройством управлять и отображаеть с него данные
* Связь сделана по Modbus
То есть, как должно работать:
а) Включили термостат или поменяли уставку - на СПК поменялись значения
б) С СПК поменяли уставку или включили-выключили - это ушло в термостат
Я делал так же, как и ты: сравнивал значения. Получалась лажа и фигня: что-то работало первым, а что-то не работало вообще.
Задача была решена через автомат состояний (State Machine) с тремя состояниями:
* Equal - оба значения равны
* ChangeUI - изменено с СПК
* ChangeHW - изменено с устройства
В каждом из ChangeXX программа находится (и не регагирует на другие изменения) пока не кончится таймаут (на случай отвала связи) или пока не выполнится операция записи новых данных в устройство и чтения их оттуда так, чтобы они совпали.
Если описать простыми словами, то получался такой алгоритм:
* Поменяли температуру с СПК? =>
* Заходим в ChangeUI =>
* Отправляем новые данные по Modbus в устройство и запускаем таймер выдержки таймаута =>
* Ждём, пока запись закончится =>
* Читаем данные из устройства =>
* Сравниваем =>
* Если равны ИЛИ если насчитали таймаут =>
* Выходим из состояния ChangeUI
Вот тогда у меня всё работало без сбоев и не было такого конфликта, когда одновременно кто-то начал менять на UI и на устройстве - и шла бесконечная перезапись значений из-за того, что они якобы поменялись.
Скажу как есть. Я программист не опытный. ST только начал использовать. Я по логике сделал всё задуманное, но работает оно не так как надо.
Пользователь capzap написал пример, который более оптимально написан, но делает тоже самое. capzap дописал DEMO, в которой часть кода имитирует те перезаписи v2 и v3, которые предполагается делать.
Когда v2 и v3 перезаписываются программно всё работает, перезапись происходит, всё синхронизируется.
Когда я запускаю отладку. В поле справа наблюдаю значения переменных.
Я кликаю на переменную, ввожу значение, потом F7, чтобы переменная его приняла. Запись происходит, всё синхронизируется, но переменная приобретает красный цвет.
Пробую записать вторую переменную, она тоже краснеет, а потом та самая проблема из-за котрой я начал эту тему.
Люди опытные подскажите, это в отладке проблема или в коде?
В железе выполняться будет нормально или как в отладке?
keysansa
09.04.2022, 13:47
Люди опытные подскажите, это в отладке проблема или в коде?
В железе выполняться будет нормально или как в отладке?
Со своего опыта я вам написал.
Прикрепляю скриншот того как выглядит переменная, когда я сам, через cds руками её перезаписываю.
60256
Какой ПЛК?
СП307 - мастер на линии RS232?
Какой ПЛК?
СП307 - мастер на линии RS232?
ПЛК 160, панель СП307.
ПЛК - slave, СП307 - мастер, SCADA - мастер.
Проверить на железе нет возможности, поэтому пишу пример, откатываю, а потом применю приём в проекте.
Таких переменных и синхронизаций будет около 80 шт.
Поэтому нужен оптимальный метод, таймеров много использовать не смогу.
Всем спасибо за вклад, проблема всё таки с отладкой, нужно оказывается снимать флаг фиксации переменной.
Нужно ставить галку снять фиксацию перменной, по умолчанию галки нет, переменная краснеет, значит фиксируется. Я этого увы не знал.
60257
Конфигурация примерно так выглядит?
Такая настройка дает возможность подключить к одной Modbus-таблице 2 мастера через Debug и RS232,
а так же еще 4-е мастера через Ethernet.
При этом все могут читать и писать (по принципу, кто последний тот и прав).
60257
Конфигурация примерно так выглядит?
Такая настройка дает возможность подключить к одной Modbus-таблице 2 мастера через Debug и RS232,
а так же еще 4-е мастера через Ethernet.
При этом все могут читать и писать (по принципу, кто последний тот и прав).
Я не знал и создал 2 таблицы. Спасибо буду знать и использовать.
А как в таком случае создать переменную в RETAIN и присвоить ей начальное значение?
kondor3000
11.04.2022, 13:18
Я не знал и создал 2 таблицы. Спасибо буду знать и использовать.
А как в таком случае создать переменную в RETAIN и присвоить ей начальное значение?
Вы бы хоть видео для новичков посмотрели или поиском поискали. Этот вопрос задают через день.
Все переменные в конфигурации, в ПЛК - слейве будут глобальные и энергонезависимые. После заливки программы в контроллер задайте начальные значения хоть руками. Можно и начальную инициализацию сделать.
ВладОвен
02.06.2022, 15:37
Решил не создавать новую тему, а продолжить здесь же, но с циклом While в ST.
Хочу создать цикл, в котором переберутся все биты байта bCount. На эти биты физически повешены 8 реле, а на реле - 8 параллельных насосов с разной производительностью.
До того, как оператор запустит программу, мне нужно по-быстрому программно пробежаться по всем возможным вариантам включения и прикинуть: а получиться ли задать нужную производительность комбинацией насосов?
Код:
FUNCTION myFunc: BOOL
VAR
bCount: BYTE := 0;
END_VAR
WHILE NOT bCount=255 DO
bCount := bCount + 1;
// IF bCount.0 THEN ......; END_IF
// IF bCount.1 THEN ......; END_IF
// IF bCount.2 THEN ......; END_IF
// IF bCount.3 THEN ......; END_IF
// IF bCount.4 THEN ......; END_IF
// IF bCount.5 THEN ......; END_IF
// IF bCount.6 THEN ......; END_IF
// IF bCount.7 THEN ......; END_IF
END_WHILE
Цикл не отрабатывается. Происходит только один проход. Потом выход из функции.
Что я сделал не так?
Что я сделал не так?
использовать, чтоб проверить все 255 комбинаций в цикле while не получится, потому что выхода получат значение переменной в последний раз записываемом в цикла плк
Малышев Олег
02.06.2022, 15:48
Не знаю на чем вы пишете, но в ST на ПР нет типа byte, есть udint. Попробовал вроде работает. И почему бы for не использовать?
FUNCTION myFunc: udint;
var_input
x:bool;
end_var
VAR
bCount: UDINT := 0;
END_VAR
WHILE NOT (bCount=255) DO
bCount := bCount + 1;
// IF bCount.0 THEN ......; END_IF
// IF bCount.1 THEN ......; END_IF
// IF bCount.2 THEN ......; END_IF
// IF bCount.3 THEN ......; END_IF
// IF bCount.4 THEN ......; END_IF
// IF bCount.5 THEN ......; END_IF
// IF bCount.6 THEN ......; END_IF
// IF bCount.7 THEN ......; END_IF
END_WHILE
myFunc:=bCount;
end_function
61044
Филоненко Владислав
02.06.2022, 15:57
Решил не создавать новую тему, а продолжить здесь же, но с циклом While в ST.
Хочу создать цикл, в котором переберутся все биты байта bCount. На эти биты физически повешены 8 реле, а на реле - 8 параллельных насосов с разной производительностью.
До того, как оператор запустит программу, мне нужно по-быстрому программно пробежаться по всем возможным вариантам включения и прикинуть: а получиться ли задать нужную производительность комбинацией насосов?
Код:
FUNCTION myFunc: BOOL
VAR
bCount: BYTE := 0;
END_VAR
WHILE NOT bCount=255 DO
bCount := bCount + 1;
// IF bCount.0 THEN ......; END_IF
// IF bCount.1 THEN ......; END_IF
// IF bCount.2 THEN ......; END_IF
// IF bCount.3 THEN ......; END_IF
// IF bCount.4 THEN ......; END_IF
// IF bCount.5 THEN ......; END_IF
// IF bCount.6 THEN ......; END_IF
// IF bCount.7 THEN ......; END_IF
END_WHILE
Цикл не отрабатывается. Происходит только один проход. Потом выход из функции.
Что я сделал не так?
А на чём Вы это запускаете?
ВладОвен
02.06.2022, 16:01
использовать, чтоб проверить все 255 комбинаций в цикле while не получится, потому что выходы получат значение переменной в последний раз записываемом в цикла ПЛК
Ну там еще надо включить общий пускатель. Так что во время перебора цикла насосы будут выключены.
Не знаю на чем вы пишете, но в ST не типа byte
Есть. Компилятор не выкидывает ошибок. Всё норм.
И почему бы for не использовать?
Хочется реализовать так, что если нужная производительность найдена (например, на 2-ом шаге), то цикл моментально прекращается и не тратит ресурсы ПЛК. Эта функция должна проверить возможность задавания аж 22 разных комбинации насосов. Т.е. ее надо будет запустить 22 раза с разным входным аргументом. Задача программы: сказать заранее оператору получиться у него или нет. Что-бы зря не начинал.
Понимаю, что через FOR тоже можно.
WHILE NOT (bCount=255) DO
Точняк! Нужны были скобки после NOT!
Заработало. Цикл перебирается полностью.
Спасибо.
А на чём Вы это запускаете?
Не совсем понял ваш вопрос.
Филоненко Владислав
02.06.2022, 16:17
Не совсем понял ваш вопрос.
У нас есть ПЛК с ST и ПР с ST - поэтому просьба уточнять, иначе путаемся мы сильно :)
ВладОвен
02.06.2022, 16:18
У нас есть ПЛК с ST и ПР с ST...
А. Понял.
У меня ПЛК.
Спасибо.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot