Вход

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



Стас Ц.
11.10.2023, 15:52
я реализовал функцию внутри функции есть кейс
При первом запуске функции проблем нет
При повторном запуске функция начинает не с кейс 0 а с того места где последний раз закончилась (понял по переменной error)


press:= getpress();
CASE PLC_PRG.iStateSetPress OF
0: // определение вектора создания давления и запуск двигателя
IF press < 0.5 THEN
IF press < pressS THEN
driveDOWN();
PLC_PRG.iStateSetPress := 1;
ELSE
driveUP();
PLC_PRG.iStateSetPress := 2;
END_IF
ELSE
IF press < pressS THEN
//driveDOWN();
PLC_PRG.iStateSetPress := 3;
ELSE
//driveUP();
PLC_PRG.iStateSetPress := 4;
END_IF
END_IF
1: // давим на зоготвку
IF press >= 0.5 THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 3;
END_IF
2: //уменьшаем давление на заготовку
IF press <= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 4;
END_IF
3: // поэтапное давление на заготовку
CASE PLC_PRG_SM.pre OF
0://проверка условия
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
ELSE
PLC_PRG_SM.pre:= 1;
driveDOWN();
END_IF
1://давим
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 2;
END_IF
2://ждём стабилизации
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 0;
END_IF
END_CASE
4: // поэтапное уменьшение давления на заготовку
CASE PLC_PRG_SM.pre OF
0://проверка условия
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
ELSE
PLC_PRG_SM.pre:= 1;
driveUP();
END_IF
1://уменьшаем давление
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 2;
END_IF
2://ждём стабилизации
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 0;
END_IF
END_CASE
5: //
6: //
7: // давим на зоготвку
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
END_IF
8: //уменьшаем давление на заготовку
IF press <= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
END_IF
9: //
targetvars.error:= 1;
END_CASE

Возможно я как-то неправильно создал функцию или ещё что-то сделал нет так?

Евгений Кислов
11.10.2023, 15:56
Не очень понятно, как вы из функции обращаетесь к переменным программы - компилятор должен был выдать ошибку.
Возможно, "функцией" вы называете не то, что под этим термином подразумевается в CODESYS.
Выложите ваш проект - посмотрим, в чем дело.

kondor3000
11.10.2023, 16:06
я реализовал функцию внутри функции есть кейс
При первом запуске функции проблем нет
При повторном запуске функция начинает не с кейс 0 а с того места где последний раз закончилась (понял по переменной error)
Возможно я как-то неправильно создал функцию или ещё что-то сделал нет так?

Функция по определению не имеет памяти и имеет только 1 выход, носящий имя функции, если у вас функция запоминает значения, то это уже ФБ. Вы даже код выложили не полностью, а только тело.
Либо эта переменная error, подана на вход функции в следующем цикле программы или присвоена при выполнении кода.

Стас Ц.
11.10.2023, 16:14
Я создал объект POU и в нем написал это код
В варе я объявил только press: real а а также в варинпут pressS
К сожелению я смогу открыть целиком код только завтра утром

Стас Ц.
12.10.2023, 08:38
FUNCTION setPRESS : REAL
VAR_INPUT
pressS: REAL; // нужное давление
END_VAR
VAR
press: REAL; // текушее давление
END_VAR
Это инициализация а дальше что мы в ней делаем


press:=getPRESS();
CASE PLC_PRG.iStateSetPress OF
0: // определение вектора создания давления и запуск двигателя
IF press < 0.5 THEN
IF press < pressS THEN
driveDOWN();
PLC_PRG.iStateSetPress := 1;
ELSE
driveUP();
PLC_PRG.iStateSetPress := 2;
END_IF
ELSE
IF press < pressS THEN
//driveDOWN();
PLC_PRG.iStateSetPress := 3;
ELSE
//driveUP();
PLC_PRG.iStateSetPress := 4;
END_IF
END_IF
1: // давим на зоготвку
IF press >= 0.5 THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 3;
END_IF
2: //уменьшаем давление на заготовку
IF press <= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 4;
END_IF
3: // поэтапное давление на заготовку
CASE PLC_PRG_SM.pre OF
0://проверка условия
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
ELSE //возможно надо сделать elseif для контроля состояния дверей
PLC_PRG_SM.pre:= 1;
driveDOWN();
END_IF
1://давим
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 2;
END_IF
2://ждём стабилизации
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 0;
END_IF
END_CASE
4: // поэтапное уменьшение давления на заготовку
CASE PLC_PRG_SM.pre OF
0://проверка условия
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
ELSE
PLC_PRG_SM.pre:= 1;
driveUP();
END_IF
1://уменьшаем давление
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 2;
END_IF
2://ждём стабилизации
PLC_PRG_SM.preX:= PLC_PRG_SM.preX + 1;
IF PLC_PRG_SM.preX >= 5 THEN
stopMOTORS();
PLC_PRG_SM.pre:= 0;
END_IF
END_CASE
5: //
6: //
7: // давим на зоготвку
IF press >= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
END_IF
8: //уменьшаем давление на заготовку
IF press <= pressS THEN
stopMOTORS();
PLC_PRG.iStateSetPress := 9;
END_IF
9: //
targetvars.error:= 1;
END_CASE

Возможно мне надо создать POU программу, а не функцию, но я всё равно не понимаю почему функция не работает

Евгений Кислов
12.10.2023, 08:47
Выложите ваш проект - посмотрим, в чем дело.

Стас Ц.
12.10.2023, 09:09
к сожелению нет
при первом запуске норм а при следующих начинает с того место где остановился

Евгений Кислов
12.10.2023, 09:12
Ваш проект не проходит компиляцию.

70883

Но, в целом, вот что можно сказать:

1. Использовать программы с VAR_INPUT - это плохой подход. Лучше перенесите эти переменные в VAR, а функцию setPRESS оформите как метод программы PLC_PRG (ПКМ на PLC_PRG - Добавление объекта - Метод)

2.


"При повторном запуске функция начинает не с кейс 0 а с того места где последний раз закончилась

Потому что значением iStateSetPress управляете вы (как уже выше указал capzap).
Если присвоите туда 0 - то функция "начинет с кейс 0".

Стас Ц.
12.10.2023, 09:18
1 попробую
2 я обнулял iStateSetPress а функция не начинала с кейса 0
ну попробую поменять на метод и буду надеятся что поможет
Спасибо за помощь

Khedron
13.10.2023, 08:04
По документации Codesys (https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_obj_program.html) программу нельзя вызывать из функции.

Programs and function blocks can call a program. A program call is not allowed in a function. There are not instances of programs.
Кроме того, PRG сохраняет свои переменные между вызовами, т.е. ведёт себя как функциональный блок, только у него нет экземпляра. У него своя собственная область памяти, общая для любых вызовов извне.
PLC_PRG с переменной iStateSetPress возможно переделать в простую функцию?