Вы оказались, как всегда, правы! После предложенных манипуляций все слетело в конфигурации ПЛК.
Придется все с нуля и вставлять мою программу руками через копирование POU
Вид для печати
Что бы не вводить все вручную, можно сделать экспорт старой конфигурации и через блокнот/notepad/д.р утилиту можно перенести конфигурацию в новую, но там нужно тоже быть осторожным.
Еще раз хочу уточнить адресацию регистров ПЛК (Slave) для внешнего компьютера (Master).
Если адрес слова (16 бит) %QW7.6.0 , то для ПК это 7 адрес?
Если адрес слова (16 бит) %QW7.7.0 , то для ПК это 8 адрес?
Вложение 58960
Зачем имеется команда "Вычислять адреса"? Что это мне дает? Из документации CodeSYS не понял ее назначение.
Я ведь писал уже раза 4 вам, считается с 0 адреса, по стрелке на вашем скрине адрес 5, распределение внутренней памяти начинается с 1 поэтому там 6,
если путаетесь всё время, сделайте комментарий для каждого 2 байт, Адрес 0, адрес 1 и т.д. Вложение 58961
Вычислять адреса надо для ПЛК, вы забейте на это, как и на %QW......
Блин, я же ошибся. Конечно 5. Я знал об об этом, но невнимательно сформулировал вопрос. Просто, не понятно, зачем так сделали, что адрес для ПК всегда меньше обозначенного на 1?
Вопрос: Зачем имеется команда "Вычислять адреса"? Что это мне дает? Из документации CodeSYS не понял ее назначение.
Вычислять адреса надо для ПЛК, вы забейте на это, как и на %QW......
Если бы вы посмотрели внимательно, галки там по умолчанию стоят Вложение 58963
Здравствуйте! ПЛК опрашивает модули по Modbus-RTU. Модули моргают, опрос идет. Но в программе вместо значений опрошенных переменных вопросительные знаки «???». Подскажите, пожалуйста, в каком направлении копать?
Вероятно вы пытаетесь смотреть работу программы в ФБ ( функциональном блоке), надо дважды щёлкнуть мышью по названию блока в левой колонке, выйдет окно,
в нём выбрать Экземпляры (иногда их может быть несколько во 2 столбце) и нажать ОК. Вложение 58968
Спасибо. Не так. Все в стандартной программе PLC_PRG. Ещё почему-то в переменные нельзя ввести и зафиксировать значения.
Вы бы хоть скрин выложили.
В PLC_PRG такое может быть только, если довольно большая программа и вся на 1 странице. Так делать нежелательно. Программу надо разбивать на блоки (ФБ)
А в конфигурации смотрели переменные?
В онлайн режиме нельзя ввести некоторые переменные, например входы ПЛК, прописанные в конфигурации. Ну и которые с вопросами, тоже нельзя.
В промежуточные и выходы можно.
Прошу помочь с установкой программы CoDeSys V2.3 на компьютер. Ставил раз пять. Раньше ставилась.
Комп Виндос 7 професиональный. Подскажите куда копать.
Dyushes
Исключите все кириллические символы из пути установки программы и библиотек.
Нет там никаких символов. Открываю скаченную (с сайта ОВЕН) программу и выполняю все требования. Как раньше далее открываю таргет файл ПЛК 160
Возможно тартет не тот, 2-3 страницы назад смотрите, тоже самое было. Либо библиотеки не туда ставите.
Даже проще можно, просто создать новый проект и посмотреть пути установки таргетов и биб-тек. Должно быть так Вложение 58982
Можно ли на языке ST обращаться к регистрам, предназначенных для внешнего компьютера, по индексам (как в массиве)?
У меня в проекте 22 регистра, распределенные в Modbus(slave) осуществляют сохранность в RETAIN памяти 22 значения от внешнего ПК.
И когда я списываю значения этих регистров в RETAIN массив, как-то некрасиво получается.
Loading_Position[1]:=Loading_Position_1;
Loading_Position[2]:=Loading_Position_2;
Loading_Position[3]:=Loading_Position_3;
Loading_Position[4]:=Loading_Position_4;
Loading_Position[5]:=Loading_Position_5;
Loading_Position[6]:=Loading_Position_6;
Loading_Position[7]:=Loading_Position_7;
Loading_Position[8]:=Loading_Position_8;
Loading_Position[9]:=Loading_Position_9;
Loading_Position[10]:=Loading_Position_10;
Loading_Position[11]:=Loading_Position_11;
Loading_Position[12]:=Loading_Position_12;
Loading_Position[13]:=Loading_Position_13;
Loading_Position[14]:=Loading_Position_14;
Loading_Position[15]:=Loading_Position_15;
Loading_Position[16]:=Loading_Position_16;
Loading_Position[17]:=Loading_Position_17;
Loading_Position[18]:=Loading_Position_18;
Loading_Position[19]:=Loading_Position_19;
Loading_Position[20]:=Loading_Position_20;
Loading_Position[21]:=Loading_Position_21;
Loading_Position[22]:=Loading_Position_22;
Имеются другие подходы? Или нормально?
Всё, что в слейве и так ретайн по умолчанию. Не надо их второй раз в ретайн пихать)
Для внешнего компа переменные в слейве будут Тег0 адрес [0], Тег1 адрес [1], Тег2 адрес [2] и т. д.
В программе вы обращаетесь к переменным слейва по имени.
Зачем вы их ещё в массив хотите запихать?
Ну вот и ответ: отдельно объявлять в VAR RETAIN это 22 записи. А если массив, то одна запись. В слейв записывать в конец это , значит, что Вы не поняли моей задачи. В слейве уже объявлены 22 регистра. А слова в RETAIN , это слова для долгострочного хранения значений регистров. Или можно регистры в слайве, как-то объявить RETAIN/
Т.е. Вы хотите сказать, что после обесточивания ПЛК и нового включения в регистрах Slave будут оставаться значения , которые были до выключения ПЛК? Если, да, то все меняется на 180 градусов! Спасибо! Меняю эту часть программы. Все упрощается радикально.
Сижу и "причесываю" код программы для увеличения быстродействия кода. На днях жду ПЛК. И обратил внимание, как я использую таймеры TON.
Пример:
...
TM_DV_2(PT:=T#150ms);
IF NOT DV_2 THEN
Flag_DV_2:=FALSE;
END_IF
TM_DV_2.IN:=DV_2;
IF TM_DV_2.Q THEN
Flag_DV_2:=TRUE;
END_IF
...
У меня на каждом цикле ПЛК отрабатывается это кусок . А почему бы "TM_DV_2(PT:=T#150ms);" не делать единожды в программе, например, на первом цикле работа ПЛК? Тем более, что параметр таймера не изменяется никогда. Что скажут специалисты? Я прав?
vsa Специалисты (ну или не очень) скажут вот что. Что приёмы программирования в ПЛК отличаются от других (некоторых) языков в том, что в ПЛК все блоки (в том числе и таймеры) обсчитываются там же, где и вызываются.
Ээээ... образно говоря, если перейти просто на схемы. Вот у нас есть это самое реле времени с задержкой на включение в настоящем мире - на DIN-рейку в щите например. И у него есть напряжение питания, которое надо на него подать, чтобы оно включилось через заданное время.
По твоей идее ты хочешь чуток кратковременно подать электропитание на это реле и рассчитывать на то, что оно каким-то хитрым образом потом останется влкюченным и само по себе сработает.
В ключе ПЛК получается так, что отсчёт времени (или другую обработку) любой блок (FB - функциональный блок) ведёт только тогда, когда его вызывают. Я этого много раз не понимал, и для меня это было откровением.
Ща я пущусь в дебри... давай подумаем, как нам самим написать свой TON и как он мог бы работать?
Сделаем так:
а) Если его IN перешёл с FALSE в TRUE - то запомним текущее время в ПЛК и заданное время PT.
б) При каждом следующем обращении к TON (вот для чего всегда нужен его циклический вызов) будем сравнивать разницу текущего времени и запомненную. Если она больше заданного PT - то включаем выход, иначе - нет.
Сделано это как раз для того, чтобы можно было прервать работу таймеров, записав в PT ноль.
Какие моменты тут можно выделить:
а) Разница прошедшего времени и заданного PT сравнивается всегда. Если PT окажется равным нулю или меньше насчитанного - то TON сразу сработает (то же справедливо и для TOF).
б) Особенность вызова FB в CodeSys такая, что если явно не заданы их параметры - то они НЕ меняются.
Да! Можно один раз написать:
TM_DV_2(PT:=T#150ms);
...но потом, чтобы он правильно считал, нужны его вызовы в коде. Циклические. В них PT меняться не будет, но для работы TON ты его должен всё равно вызывать. Хоть без аргументов, но должен:
TM_DV_2();
Поэтому, что ты напишешь с PT, то без - пофиг. Но вызывать надо все FB циклически.
Cs-Cs, тема закрыта. Убедительно ответили. И я проверил на практике - не работает, если только на первом цикле обратится к таймеру для начала работы (TM_DV_2(PT:=T#150ms); ). Спасибо!
Напишу попроще, можно написать TM_DV_2(); Тогда РТ надо задать в предыдущей строке TM_DV_2.PT:=T#150ms;
Можно написать TM_DV_2(PT:=T1); Т1 задать в объявлении переменных T1 : TIME:=T#150ms;
Но если у вас 10 таймеров, то надо задать 10 штук T1 : TIME:=T#150ms; T2 : TIME:=T#150ms; T3: TIME:=T#150ms; и т.д.
За причесывание кода... Быстродействие кода с таймерами - далеко под сомнением.
Там где нужно быстродействие, там каждый цикл на счету, какие там таймеры?
Валенок Спасибо за фишку инициализации FB сразу с параметрами ^_^. Я такое мимио глаз пропустил. Я про это - очень круто!
Цитата:
VAR
TM_DV_2 : TON := (PT := T#150ms); //"параметр таймера не изменяется никогда" (С)
END_VAR
Тогда таймеры выносятся в обслуживающий код.
"Причесывание" кричного ко времени кода совсем не так выглядит. Там за 150мс может все кардинально измениться.
А конкретно тут - оптимизировать нечего. Программа 100% будет выполняться раз в 5 быстрее таймера, по фактическому времени.
Ну, вот у вас таймер, 150 мс.
Время цикла какое? 100? 200 мс? Или 10?
Тут разные оптимизации...
Большое спасибо за отклик на мой вопрос.
В приведенном фрагменте используется TON таймер. Задача такая: имеется подъемное устройство, которое должно при подъеме груза останавливаться на верхнем датчике. Но опыт эксплуатации подобных подъемников показал, что останавливается подъемник не в середине датчика, а в самом его начале. И при больших грузах (300-500 кг) при снятии напряжения с электродвигателя, пока срабатывают механические тормоза, груз немного опускается и сходит с верхнего датчика. И сигнал от датчика теряется. Конечно я управляю движением частотным преобразователем. И все скажут, что нужно было отстраивать определенные параметры частотного преобразователя в режиме торможения. Тем более, что я их и настраиваю. Но иногда это не помогает. И я исправляю аварийную ситуацию простым таймером, который немного задерживает сигнал от верхнего датчика на 150ms (значение настраивается при наладке оборудования) и передает в программу состояние DV_2 в виде Flag_DV_2.
И Вы хотите сказать, что пример моего таймера не выполнит поставленную задачу? Тут главное, что Flag_DV_2 должен быть в TRUE всегда пока имеется сигнал от DV_2. И в программе я контролирую не сам сигнал от датчика, а его флаг Flag_DV_2.
И еще, я таким образом убираю кратковременное появления сигнала DV_2 от помех на линии. Подобными алгоритмами обрабатываю и кнопочные станции. Уж очень помеховосприимчивы линии связи от кнопок. Тем более, когда работают частотные преобразователи на маленьких частотах.