PDA

Просмотр полной версии : ПРавильное оформление функции



RomeoVar
09.05.2021, 15:07
Добрый день знатоки.
Разрабатываю на ПЛК-210-3 (но не суть). Опыта в работе именно на CODESYS маловато. Помогите решить задачу.
Суть: необходимо записывать параметры в серводрайвер по MODBUS. Запись осуществляется по переднему фронту переменной (GVL.stServo[roller_drive].stRWFlags.xWrIntPosReg3). В Приложении этим занимается отдельная задача с периодичностью 250 мс. После записи я опять-же по фронту переменной (GVL.stServo[roller_drive].stRWFlags.xRdIntPosReg3) считываю данные и проверяю соостветствие. Если данные совпадают - запись успешна, если нет - ОШИБКА. Код примерно такой :
CASE iCalcMarkSet OF
/// Записываем параметры в серво и проверяем корректность записи {{{
0:
GVL.stServo[roller_drive].stWrServo.stIntPos[3].unIntPos.dwDWORD :=
GVL.stServoDrivePrms[roller_drive].dwStretchLenInPos3;
GVL.stServo[roller_drive].stWrServo.stIntPos[3].wIntPosSPD :=
GVL.stServoDrivePrms[roller_drive].wRpmInPos3;
GVL.stServo[roller_drive].stRWFlags.xWrIntPosReg3 := TRUE;
iCalcMarkSet := 1;
1:
GVL.stServo[roller_drive].stRWFlags.xWrIntPosReg3 := FALSE;
GVL.stServo[roller_drive].stRWFlags.xRdIntPosReg3 := TRUE;
iCalcMarkSet := 2;
2:
GVL.stServo[roller_drive].stRWFlags.xRdIntPosReg3 := FALSE;
xErrWrMarkSetPrms := FALSE;
IF GVL.stServo[roller_drive].stRdServo.stIntPos[3].unIntPos.dwDWORD = GVL.stServoDrivePrms[roller_drive].dwStretchLenInPos3
AND GVL.stServo[roller_drive].stRdServo.stIntPos[3].wIntPosSPD = GVL.stServoDrivePrms[roller_drive].wRpmInPos3 THEN
iCalcMarkSet := 3;
ELSE
xErrWrMarkSetPrms := TRUE;
iCalcMarkSet := -1;
stBtnState.xBtn.MarkSet := FALSE;
END_IF
3:

Вопросов несколько:
1. МОжно ли проверить успешность записи флагами самого MODBUS и если да - как это сделать?
2. Т.к. я записываю данные множество раз - хочу реализовать функцию (или функциональный блок). Но не хочу использовать циклов (очень нежелательно). Как это правильно сделать - использовать VAR_STAT тоже не хочется, вызывать несколько раз функцию- вызвал, записал данные, взвел флаг записи. Снова вызвал - снял флаг, снова вызвал - взвел флаг чтения ну и так далее.
Подскажите - как оптимально решить задачу такого рода?
Заранее признателен

Евгений Кислов
09.05.2021, 15:29
Добрый день.

1. Это возможно. Нужно использовать режим записи Приложение.
https://faq.codesys.com/pages/viewpage.action?pageId=24510480

Пример в FAQ не совсем полный, но после изучения входов/выходов ModbusChannel - всё должно стать понятно.

2. Что именно вы хотите вынести в функцию и каковы критерии оптимальности? ("как оптимально решить задачу такого рода")

RomeoVar
09.05.2021, 16:13
Попробую объяснить:
Я отправил данные слейв-устройству. Есть ли встроенные переменные - значения которых содержат информацию о том, успешно ли данные обработаны слейвом (записаны в регистры), не произошло ли ошибки при передаче, приеме, подтверждении отправленных данных? Или мне самостоятельно, в коде, нужно проверять запись данных опросом слейва на чтение?
Вот в чем вопрос первый.

А второй, по функции: я хотел-бы запись и контроль успешной записи реализовать в отдельную функцию. Но...
В моем понимании проблема заключается в том, что на запись данных требуется время (отправить пакет по шине, получить ответ от слейва как минимум 50 мс.). Тогда мне в функции нужно либо реализовать цикл чтобы дождаться окончания отправки пакета слейв-устройству. После этого запросить данные, опять- таки дождаться ответа слейва. Потом проверить и вернуться в основную программу. Очевидно таким образом реализованная функция будет медленной. Вот и вопрос, как реализовать такую функцию без цикла?
А может есть системные переменные, о которых я не знаю, содержащие информацию о результате отправки последнего пакета по шине (например)?

RomeoVar
09.05.2021, 16:23
Вот у меня скрин работающей шины. Я правильно понимаю что если после передачи данных устройству переменная xError = FALSE то данные записаны успешно?55026

Евгений Кислов
09.05.2021, 17:35
Вот у меня скрин работающей шины. Я правильно понимаю что если после передачи данных устройству переменная xError = FALSE то данные записаны успешно?55026

Признак успешной записи для конкретного канала опроса (iChannelIndex) - это xDone = TRUE.

RomeoVar
10.05.2021, 10:49
НУ тоже задача не очень прозрачная. в программе, по таймингам нужно успеть отловить значение iChannelIndex = требуемый к***** и дождаться чтобы xDone принял значение True. О, возникла идея - а что если создать задачу по событию фронт xDone и назначить PRG в которую передавать требуемый iChannelIndex и только после этого "писать" данные в канал ну и потом спокойно обрабатывать значения xDone xError?

Евгений Кислов
10.05.2021, 11:13
НУ тоже задача не очень прозрачная. в программе, по таймингам нужно успеть отловить значение iChannelIndex = требуемый к***** и дождаться чтобы xDone принял значение True. О, возникла идея - а что если создать задачу по событию фронт xDone и назначить PRG в которую передавать требуемый iChannelIndex и только после этого "писать" данные в канал ну и потом спокойно обрабатывать значения xDone xError?

Возможно, вам будет проще обмен через библиотеку реализовать:
https://youtu.be/8HdrbW9blsk

RomeoVar
13.06.2021, 13:22
Через библиотеку уже не хочется.
Реализовал через проверку xError в связке с xDone & iChannelIndex через глобальную переменную
Спасибо за подсказку