Вход

Просмотр полной версии : Некорректное выполнение ST-кода в эмуляторе и на виртуальном контроллере



papikrus
22.12.2025, 15:43
Доброго дня, Уважаемые!
...если попал не по адресу, просьба модераторам указать правильный путь с уведомлением...
Просьба читать до конца!
Вот сваял код (в прикреплённых файлах zip-архив с .projectarchive или zip-архив с .project)...
СПК210 codesys v3.5 sp17 patch 3 (32bit) owentarget 3.5.17.35

описание, как должно работать:
1 - выбираем последовательнось чек-боксов случайным образом, то есть отмечаем в любой последовательности
любой чек-бокс во всех трёх стобцах;
2 - при выборе чек-бокса весь столбец становится неактивным для ввода,
чтобы не выбрать ещё один чек-бокс в этом столбце;
3 - при первой отметке чек-бокса появляется кнопка reset для сброса ошибочного выбора,
нажатие на неё сбрасывает ошибочно выбранные чек-боксы,
если выбор сделан как в одном, так и в двух и в трёх столбцах;
4 - при сбросе все чекбоксы становятся активными для ввода;
5 - при выборе правильной необходимой последовательности fl_18_x-fl_12_x-fl_13_x появляется кнопка ok
6 - при нажатии на неё данная последовательность "фиксируется",
то есть выбранные чек-боксы остаются неактивными,
в то время как невыбранные активируются для ввода,
некоторые переменные принимают соответствующие значения,
кнопки reset и ok исчезают,
7 - можно переходить к выбору следующей последовательности, причём при её сбросе
на любом этапе выбора чек-боксов (нажатие reset)
предыдущая последовательность остаётся актуальной.

НО !!!!! ---

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

з.ы. но если установить для отладки точку останова,
скажем, в строке 81 или 103 всё "работает как швейцарские часы";
пробовал "выловить" этот баг , установливая точки останова подряд,
но в таком режиме работы всегда всё окей... где затык? помогите разобраться!
спасибо!

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

kondor3000
22.12.2025, 19:18
Проблема в том, что в массивах разное кол-во переменных и рядов в визуализации, 87343
добавил во второй массив 4 переменных и в циклы тоже, во 2 столбец третий ряд, все 3 ряда отработали правильно.

Из за вложенных циклов переменные fl_18_8 и fl_12_2 становятся неактивны. 87344
Массивы и циклы лучше сделать на 1 переменную больше.
Сделайте по 8 рядов, а массивы и циклы по 9 переменных и всё будет работать.

Евгений Кислов
23.12.2025, 07:44
Добрый день.

На мой взгляд, описанная в первом посте проблема имеет следующую причину: переменная PLC_PRG.clk_btn_2 привязана к свойству кнопки Нажатие.
Т.е. эта переменная имеет значение TRUE, пока кнопка нажата. С учетом человеческой скорости реакции - даже однократное "быстрое" нажатие фиксирует кнопку как минимум на 100 мс.
За это время успевает пройти 10 циклов MainTask.
В первом из них всё нормально, но при этом выполняются строки:



IF clk_btn_2 THEN
...
num_sel_13 := 0;
...
num_sel_12 := 0;
...
num_sel_18 := 0;
END_IF


И из-за этого во втором цикле при попадании в этот IF происходит:



app_13[0] := TRUE;
app_12[0] := TRUE;
app_18[0] := TRUE;


Но эти массивы нумеруются с 1, и при обращении к элементу с индексом 0 происходит "порча" памяти:



// Порядок объявления массивов: app18, app12, app13
app_13[0] := TRUE; // фактически записываем TRUE в app_12[2]
app_12[0] := TRUE; // фактически записываем TRUE в app_18[8]
app_18[0] := TRUE; // что-то еще перезаписываем, но сейчас это не так интересно


Т.к. app_18[8] и app_12[2] становятся в TRUE, то соответствующие inact_18[8] и inact_12[2] тоже устанавливаются в TRUE.

Этим и объясняется наблюдаемая картина.

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

P.S. - еще есть проблема в этом фрагменте:



IF flag_13[num_sel_13] AND flag_18[num_sel_18] AND flag_12[num_sel_12] THEN
btn_2 := TRUE;
ELSE
btn_2 := FALSE;
END_IF


Он выполняется вне каких-либо условий каждый цикл ПЛК, но при этом в момент запуска приложения и вплоть до начала манипуляций в визуализации переменные num_sel_13, num_sel_18 и num_sel_12 имеют значение 0 - а flag-массивы нумеруются с 1.

P.P.S. - весь код можно существенно упростить, отказавшись от большинства (если не всех) циклов.

papikrus
23.12.2025, 08:26
Евгению отдельное Спасибо, буду разбираться. (если честно были подозрения на "неправильную" нумерацию и "человеческую скорость реации" при нажатии... на днях переиграю, отпишусь.

спасибо и kondor3000, но -- задачу необходимо необходимо решать именно с таким количеством чек-боксов!

mozgichok
23.12.2025, 08:33
Ограничьте выполнения 4 секции одним циклом.
873468734787348
IF clk_btn_2 AND counter < 1 THEN
counter := counter + 1;
END_IF

papikrus
23.12.2025, 10:32
Всем Спасибо!
Решил проблему изменив конфигурацию кнопок ok и reset в визуализации - переменные clk_btn_1 и clk_btn_2 отвязал от "нажатие" (длинный 'человеческий' импульс") и привязал к OneMouseDown (короткий "компьютерный" передний фронт импульса соответствующих переменных) и соответственно добавил в конец соответствующих (без тавтологии в технических описаниях обходиться трудно, не хватает синонимов :-) условий строки clk_btn_X := false; , чтобы вернуть после выполнения этих условий переменные в исходное состояние (false). Беру на заметку! Кстати, в первоначальной версии https://owen.ru/project/avtomatizacija_molokopererabatyvayushchego_zavoda (но там код вообще "крутой" и "аховый", потому что учились, а делать надо..) сделано было именно через передние и задние фронты RT_RIG FT_RIG и именно в коде, поэтому-то, наверное, и работает без ошибок.

Нескромный вопрос к Евгению Кислову! ""P.P.S. - весь код можно существенно упростить, отказавшись от большинства (если не всех) циклов."" --- намекните как? мы тут решили заняться оптимизацией и унификацией кода, думаю Вы, догадались, но навыков не хватает...

з.ы. кстати про нумерацию в массивах и в индексах циклов тоже спасибо за замечание..

Евгений Кислов
23.12.2025, 10:35
Нескромный вопрос к Евгению Кислову! ""P.P.S. - весь код можно существенно упростить, отказавшись от большинства (если не всех) циклов."" --- намекните как? мы тут решили заняться оптимизацией и унификацией кода, думаю Вы, догадались, но навыков не хватает...

Свяжитесь, пожалуйста, со мной в телеграм (см. в подписи), чтобы более предметно это обсудить.