PDA

Просмотр полной версии : Modbus TCP и ретентив



@ND
04.02.2016, 06:48
Зачастую нужно, чтоб была возможность записи уставок с верхнего уровня по протолу modbus tcp.
3й функцией читать, 6/16 записывать.

Но тут есть такой подводный камень:

При выключении контроллера, все эти уставки обнулятся, так как они хранятся в области входов %I.
Как сделать, чтоб они сохраняли своё значение?

Можно конечно придумать костыль, добавить специальный флаг для записи и тогда читать уставку придётся читать из одного места, а записывать в другое.
Как правило системы верхнего уровня очень неповоротливые и не имеют возможности для таких костылей или просто не хотят, по крайней мере у нас обычно такие попадаются.

Так же у контроллеров ОВЕН зачем то сделано так, что нельзя писать из программы значения в область входов %I, что могло бы решить эту проблему.

Пробовал такую конструкцию:

VAR_GLOBAL RETAIN
aa AT %IW0 : WORD;
END_VAR

Но она не работает, переменная "аа" не сохраняет значение всё равно.

Были так же безумные идеи при старте контроллера писать по modbus tcp в самого себя сохранённые значения уставок, но это уже какое то жёсткое порно!
И даже этому не суждено быть, так как контроллер почему то на запросы по порту начинает отвечать не сразу, как стартует программа, а спустя какое то сферическое время, после старта программы, секунд 15-20.

Как быть то?

Работаю с СПК207-03-CS-WEB
КДС 3.5 SP5 Patch 5

capzap
04.02.2016, 07:15
Так же у контроллеров ОВЕН зачем то сделано так, что нельзя писать из программы значения в область входов %I, что могло бы решить эту проблему.
попробуйте у сименса что нибудь сохранить в области IW, дам сто рублей если получится
Для хранения уставок, должен быть специально выделенная глобальная ретайн структура, иначе ни как

@ND
04.02.2016, 07:43
попробуйте у сименса что нибудь сохранить в области IW, дам сто рублей если получится
Для хранения уставок, должен быть специально выделенная глобальная ретайн структура, иначе ни как

http://s8.hostingkartinok.com/uploads/images/2016/02/8bb908446ca6fd7078ac82e4ea66bac6.png (http://hostingkartinok.com/show-image.php?id=8bb908446ca6fd7078ac82e4ea66bac6)

Вознаграждение принимается на yandex money 410012466052729 :cool:

capzap
04.02.2016, 07:48
э нет, мы про ретайн говорили, нажмите ка стоп а потом включите

ЗЫ а так понятно откуда Ваши заблуждения, каюсь не правильно сформулировал. Постоянно записанные константы в таком виде будут отоброжаться конечно, но тогда надо записывать из вне постоянно уставку, а так как обмен длится несколько дольше, то в некоторые циклы эти значения обнулятся, так же и в Вашем примере начните писать в эту область через срабатывание таймера и на на выходе будет в основном ноль стоять а не константа

@ND
04.02.2016, 07:53
э нет, мы про ретайн говорили, нажмите ка стоп а потом включите

Вообще то вы процитировали мое утверждение о том, что я ругался на то что нет возможности записать значение в %I.
И если бы такая возможность была, я бы смог из ретентив структуры, при старте контроллера сохранить значение в %IW0

Поэтому считаю себя выйгравшим в этом ивенте на 100 руб.

Я сначала сохранил значение 12345 в IW0, затем сохранил значение 4321 в IW0

@ND
04.02.2016, 08:09
э нет, мы про ретайн говорили, нажмите ка стоп а потом включите

ЗЫ а так понятно откуда Ваши заблуждения, каюсь не правильно сформулировал. Постоянно записанные константы в таком виде будут отоброжаться конечно, но тогда надо записывать из вне постоянно уставку, а так как обмен длится несколько дольше, то в некоторые циклы эти значения обнулятся, так же и в Вашем примере начните писать в эту область через срабатывание таймера и на на выходе будет в основном ноль стоять а не константа

Дак галка с самого начала была убрана, и ничего у меня не обнулялось. И записывать постоянно не обязательно.
http://s8.hostingkartinok.com/uploads/images/2016/02/72ee03723242349e2cf8cbd26fc7a69e.png (http://hostingkartinok.com/show-image.php?id=72ee03723242349e2cf8cbd26fc7a69e)
PS: Жду поступлений :)

capzap
04.02.2016, 08:19
PS: Жду поступлений :)
да сейчас, я тоже могу картинку выложить, то же самое что и в семене в таком случае, где foo AT %IW0 : WORD;
сможете объяснить почему 4321 записаная во втором нетворке отображается в переменной foo первого нетворка, а сама IW0 равна нулю. КДС в этом плане намного правильнее семена отображает значения, а объяснения у всех одни и те же
Так как физические входы получают свои значения непосредственно из подключенных к ним полевых устройств, то запись в эти входы запрещенацитата из доков на плк от семена

@ND
04.02.2016, 08:28
Не нужно путать физические входы (типа PIW0) с областью процесса (IW0)
В PIW0 я уже ничего не смогу записать, а в IW0 пожалуйста.
И если IW0 не привязан ни к какому входу, то записанное туда значение сохранится сколь угодно долго.

@ND
04.02.2016, 08:32
да сейчас, я тоже могу картинку состряпать, где foo AT %IW0 : WORD;
сможете объяснить почему 4321 записаная во втором нетворке отображается в переменной foo первого нетворка?
Как компилятор вас пропустил для записи в %IW0 ?
У меня ругается

capzap
04.02.2016, 08:38
незнаю, но в окне вывода стоят две ошибки, наверное из-за того что правильный код я заменил онлайн изменением

capzap
04.02.2016, 08:39
Не нужно путать физические входы (типа PIW0) с областью процесса (IW0)
В PIW0 я уже ничего не смогу записать, а в IW0 пожалуйста.
И если IW0 не привязан ни к какому входу, то записанное туда значение сохранится сколь угодно долго.
выйду на улицу, попадется терминал, переведу

@ND
04.02.2016, 08:41
да сейчас, я тоже могу картинку состряпать, где foo AT %IW0 : WORD;

Вы думаете я эту картинку состряпал?
Могу выложить проект, могу видео.

capzap
04.02.2016, 08:46
Вы думаете я эту картинку состряпал?
Могу выложить проект, могу видео.

текст я уже изменил, а потом у меня нет опыта оставлять в этой области пустые места, по этому я и не предполагал про такое поведение неиспользуемой области I

@ND
04.02.2016, 08:50
А всё таки, если вернуться к первоначальной задаче, может быть существует какой нибудь способ записать значение в %IW0, пускай хоть и не явный?

capzap
04.02.2016, 09:10
та через костыли то можно всё что угодно, касаемо модбас, хоть и стоит IW но это регистры хранения, надо смотреть что происходит с теми регистрами, которых не касается визуализация, если они ни сохраняют свои значения после включения, значит идет удаленное обнуление тех кто связан с HMI, в ИП320 такое решалось с включением панели позже чем плк, тут наверное что то подобное должно быть

@ND
04.02.2016, 09:21
та через костыли то можно всё что угодно, касаемо модбас, хоть и стоит IW но это регистры хранения, надо смотреть что происходит с теми регистрами, которых не касается визуализация, если они ни сохраняют свои значения после включения, значит идет удаленное обнуление тех кто связан с HMI, в ИП320 такое решалось с включением панели позже чем плк, тут наверное что то подобное должно быть

Под верхним уровнем я имею ввиду не HMI, а различные ЛПУМГ, ЦЩУ, диспетчерские, где не наша зона ответственности, и возможности что то менять там нет.
А там ребята не любят вставлять костыли, иногда просто не хотят, мотивируя что это не возможно впринципе на их системе.

На сколько я понимаю все регистры для 3, 6, 16 функции хранятся в %I, и не важно с чем они связаны, а область %I при выключении контроллера обнуляется.

capzap
04.02.2016, 09:29
значит надо переходить на библиотеки, проверять наличие соединения и после этого подключать слейв в свободный доступ и вместо штатного ретайна, самостоятельно при пуске вычитывать данные из файла, ну и запись производить по приходу изменения

@ND
04.02.2016, 09:43
значит надо переходить на библиотеки, проверять наличие соединения и после этого подключать слейв в свободный доступ и вместо штатного ретайна, самостоятельно при пуске вычитывать данные из файла, ну и запись производить по приходу изменения

Не совсем понял идею.

Собственно что мне нужно:

Смотреть, менять значения уставок по месту (на СПК207)
Смотреть, менять значения этих же уставок с верхнего уровня (ВУ).
И что бы значения уставок сохранялись при выключении/включении контроллера.
(ВУ) хочет читать уставку и записывать её по одному адресу регистра хранения.
Читать уставку (ВУ) будет периодически, записывать непосредственно один раз при вводе/изменению.


Как это реализовать на СПК207, я пока не вижу, наверное это невозможно.

RASP
05.02.2016, 16:55
Господа из Siemens просто ввели всех в заблуждение. Области памяти IW,QW пришли из S5, где была жесткая адресация от положения модуля. В S7 свободная адресация, поэтому , пока входной модуль не привязан к конкретному адресу он свободен и в него можно записывать. Это было сделано для конвертации программ. Народ это быстро пронюхал. Брали один процессор, без модулей, или PLCSYM и в него по OPC засылали значения по этим адресам, чтобы имитировать реальную периферию. В результате все быстро научились делать имитаторы установок и отлаживать все программы без реального железа.Но после того как ты поставил модуль и привязал к этому адресу начинается постоянный обмен и в этот адрес по OPC уже ничего не заслать. Другими словами, это обычные глобальные данные, точно такие же как в CODESYS, просто Siemens их так назвал и привязал к использованию с периферией. Так как для нормальной работы есть еще MW и блоки данных, конечно их как правило не используют для других целей. Также и в CODESYS никто не использует периферийные адреса. Для этого есть обычные глобальные данные. А для тех целей что описаны выше, как правило делают семафоры.

@ND
08.02.2016, 06:41
А для тех целей что описаны выше, как правило делают семафоры.

Что это за семафоры? И как их реализовать?

Предложите мне нормальную реализацию моей задачи, дам 100руб :)

@ND
08.02.2016, 06:46
Также и в CODESYS никто не использует периферийные адреса. Для этого есть обычные глобальные данные.

Да я бы с удовольствием их бы и не использовал, но CODESYS привязал протокол модбас к периферийной области памяти. Из за чего невозможно тогда с ним нормально работать.
Какой смысл вообще тогда в реализации 3й функции в CODESYS, если прочитать можно то, и только то, что было записано 6й функцией?

@ND
08.02.2016, 07:16
Господа из Siemens просто ввели всех в заблуждение. Области памяти IW,QW пришли из S5, где была жесткая адресация от положения модуля. В S7 свободная адресация, поэтому , пока входной модуль не привязан к конкретному адресу он свободен и в него можно записывать. Это было сделано для конвертации программ.

Это называется асинхронный метод опроса физических входов.
Механизм характеризуется запросами к физическим входам (PIW) независимо от запроса к области процесса (IW). Обычно запросы к (PIW) осуществляются периодически в собственной задаче опроса отдельно взятого контроллера и блоками по несколько сигналов. При этом запросом к (IW) возвращается значение, полученное последним сеансом связи с (PIW). С помощью этого метода можно обеспечить оптимизацию временного ресурса, затраченного на один сигнал, и тем самым увеличить максимальное количество опрашиваемых сигналов за интервал времени опроса.

В качестве примера рассмотрим промышленный ПЛК Siemens S7-315 при опросе его по шине Profibus (1,5 Мбит/с). Среднее время обработки MPI-запроса этим контроллером составляет 30 мс. Если использовать синхронный механизм для каждого сигнала, т.е. один запрос на каждый сигнал, то в течении одной секунды мы сможем получить около 33 сигналов. А если применить асинхронный механизм, т.е. в одном MPI-пакете получать до 220 байт или 110 сигналов целочисленного типа на 16-разрядов, то мы сможем за одну секунду получить до 3630 сигналов. Как можно видеть, эффективность асинхронного механизма в данном случае составляет 110 раз, а именно значение максимальной ёмкости MPI-пакета.

Недостатком асинхронного механизма является то, что запрос значения атрибута параметра возвращает не актуальное на момент запроса значение, а значение последнего сеанса опроса контроллера. Впрочем, если учесть, что источник данных может обновляться с периодичностью аппаратных ограничений АЦП, да и сами датчики могут иметь определённые ограничения в скорости реакции, то применение асинхронного механизма сбора может иметь серьёзные основания, а не потому, что это необходимо для какой то там конвертации.

RASP
08.02.2016, 14:37
Как я и говорил Siemens всех запутал. Есть PII, PIO, PIW, IW, OW, MW, DB, TEMP. Физические входа/выхода и области операндов(куда входят и образы процессов) не одно и тоже.
Впрочем разговор о CODESYS. Как я понял речь идет не локальной периферии, а о удаленной периферии или передачи данных по сети. И речь идет о CODESYS 3. Если честно не совсем понял, почему Вы используете IW и QW, а не хотите подключить например массив. Функции 3 и 16 (если речь идет о Modbus) позволяют за один цикл опрашивать больше 220 байт, а скорость по Modbus TCP может быть больше 1,5 Мбит/с. Впрочем если Вы любите Profibus, есть много достойных фирм у которых контроллеры работают на CODESYS и при этом есть эта достойнейшая сеть (от которой сам Siemens уже много лет пытается отойти). Лично мне гораздо больше нравится EtherCat, CAN, Modbus TCP, TCP/IP. Кстати, в CODESYS можно не использовать для работы с сетями "конфигуратор", а работать с сетевыми библиотеками напрямую, с помощью библиотек, через буферы обмена и даже лепить свои собственные протоколы.
По поводу семафора:

Семафо́р — объект, ограничивающий количество потоков, которые могут войти в заданный участок кода.
Это к тому, что одновременный доступ из нескольких мест к переменной, с возможностью записи, является очень плохим вариантом решения задачи.

amn
08.02.2016, 18:13
Не совсем понял идею.

Собственно что мне нужно:

Смотреть, менять значения уставок по месту (на СПК207)
Смотреть, менять значения этих же уставок с верхнего уровня (ВУ).
И что бы значения уставок сохранялись при выключении/включении контроллера.
(ВУ) хочет читать уставку и записывать её по одному адресу регистра хранения.
Читать уставку (ВУ) будет периодически, записывать непосредственно один раз при вводе/изменению.


Как это реализовать на СПК207, я пока не вижу, наверное это невозможно.

. Организуем слэйв для уставки из верхнего уровня (далее ВУ).
. Заводим глобальную переменную для уставки по месту (далее "переменная по месту").
. Заводим глобальную рабочую переменную текущей уставки, которая будет использоваться в программе.

При первом старте:
. ПЛК читает уставку из файла.
. записываем прочитанную уставку в слэйв ВУ и в переменную по месту.

Делаем ФБ
входы:
. уставка ВУ
. уставка по месту

вместо выхода используем глобальную переменную (или VAR_IN_OUT):
. уставка текущая

ФБ на свои входы получает уставки из двух мест и контролирует их изменение.
1. Уставку по месту постоянно сравниваем с текущей (рабочей). Если изменилась, то присваиваем ее значение текущей и в слэйв ВУ.
2. Если изменилась уставка ВУ, то присваиваем ее значение текущей (рабочей).
Для того, чтобы менять уставку по месту используем переменную уставки по месту, а для отображения по месту используем текущую (рабочую).

Если проверяем изменения именно в таком порядке, то приоритет имеет уставка от ВУ.

После каждого изменения текущей (рабочей) уставки сохраняем значения в файл. Из него данные будут читаться при включении ПЛК (вместо РЕТАИН).

@ND
09.02.2016, 06:43
. записываем прочитанную уставку в слэйв ВУ и в переменную по месту.

Всё бы хорошо, да только есть одна проблема!

22511

Как я уже говорил выше, не получается записывать значения в область памяти %I, хоть через соотнесение переменных, хоть напрямую!
Вот он корень зла!!!

@ND
09.02.2016, 09:50
Если честно не совсем понял, почему Вы используете IW и QW, а не хотите подключить например массив. Функции 3 и 16 (если речь идет о Modbus) позволяют за один цикл опрашивать больше 220 байт, а скорость по Modbus TCP может быть больше 1,5 Мбит/с.

А какая разница?
Я всё равно не могу записать значение из программы контроллера, хоть в %IW, хоть в соотнесённую переменную.
И потом, так же без разницы, что ты будешь обрабатывать в программе 10 шт IW, или 10 шт переменных массива.

capzap
09.02.2016, 10:30
а что там получается если объявить foo AT %IW500 : WORD;
а в проге aa[3]:=foo; добавить вместо прямого присваивания области IW и еще как себя ведет если aa[3]:=aa[0]; в окне слейва тоже ни чего не отображается?

@ND
10.02.2016, 06:17
а что там получается если объявить foo AT %IW500 : WORD;
а в проге aa[3]:=foo; добавить вместо прямого присваивания области IW и еще как себя ведет если aa[3]:=aa[0]; в окне слейва тоже ни чего не отображается?

Получается вот так:

22544

если я в foo ничего не могу записать, то нет тогда ни какого смысла её кому то присваивать.


В окне слейва, что я выкладывал на предыдущем скрине как раз значения отображаются, но реально там нули, я же показывал.

А ещё пробовал вот так:
22546

@ND
16.03.2016, 09:05
Вернулся к проблеме:

Попробовал вот так:
23165

Всё равно не получается.
Как работать с уставками записываемых по модбас?
Как сделать так, чтоб они сохранялись при вкл/выкл контроллера?

Наверняка кто то в своих проектах это решал.

Валенок
16.03.2016, 13:22
При надежде на ретайн.

x_где_то_в_слейве : тип;


var retain
x : тип;
end;
var
init : bool;
end;
------------------
if not init then
init := true;
x_где_то_в_слейве := x;
end_if
x := x_где_то_в_слейве;

Все. Работаем с x_где_то_в_слейве

@ND
17.03.2016, 06:14
x_где_то_в_слейве := x;

"x_где_то_в_слейве" Эта переменная у вас принадлежит области %IW ? (А записывать значения 6/16 функцией можно только в %IW)
Если да, то это не сработает.

Валенок
17.03.2016, 11:54
Какой бредовый тут слейв в отличие от кдс-2

меняем
x_где_то_в_слейве := x
на
sysmemcpy(adr(x_где_то_в_слейве),adr(x),sizeof(x)) ; //или как там она с копированием


или


program пихаем
var_in
оттуды : тип;
end_var
var_in_out
cюды : тип;
end_if
---------
сюды := оттуды;
---------




------------------
var retain
x : тип;
end;
var
init : bool;
end;
------------------
if not init then
init := true;
пихаем(сюды := x_где_то_в_слейве; оттуды := x);
end_if
x := x_где_то_в_слейве;

@ND
17.03.2016, 12:48
23182

23183

Что то как то не получается :(

Валенок
17.03.2016, 13:59
почему с sysmemcpy - х.з., под рукой кдс3 нету, видимо либ-ка не подключилась
pihaem - это не функция, при вызове поля нужны

пихаем(сюды := x_где_то_в_слейве; оттуды := x);

@ND
17.03.2016, 14:06
23185

Ну тогда так.

Валенок
17.03.2016, 14:55
а никак через вменяемое имя без % ?

PS
Ну вот, если забросить эти дурацкие at% все и работает. Кажется ))

@ND
18.03.2016, 06:53
а никак через вменяемое имя без % ?

PS
Ну вот, если забросить эти дурацкие at% все и работает. Кажется ))

23200

Всё таки не работает!
Вываливает предупреждение.
Хоть и в онлайне показывает что в соотнесённой переменной для %IW0 значение 123, но в реальности там 0 !!!


в программе переменная а:
VAR_GLOBAL RETAIN
a: ARRAY[0..9] OF WORD;
END_VAR

@ND
18.03.2016, 07:12
23201

Так тоже не работает.
В общем похоже это тупиковое направление решения задачи.

@ND
18.03.2016, 07:37
Нашёл я решение своей проблеммы!!!

Стандартная библиотека IoDrvModbusTCPSlave - полнейшее @#$%^&*

Нужно использовать другую библиотеку: ModbusTCPSlave - там всё ок!!!

23202
23203

Валенок
18.03.2016, 08:48
А Вы говорили тупиковое. А делов-то - прокладки левые.
И почему в п#35 - "шина не запущена" ?

PS
Все новое .. просто см. п#24 от amn

@ND
18.03.2016, 09:40
А Вы говорили тупиковое. А делов-то - прокладки левые.
Что за прокладки?


И почему в п#35 - "шина не запущена" ?
Не запущена потому что есть ошибка при компиляции.


Все новое .. просто см. п#24 от amn
Дак выяснили же, что этот метод не работает с библиотекой IoDrvModbusTCPSlave.
В КДС3 нет возможности записать в %IW ни каким способом.

Валенок
18.03.2016, 23:57
Что за прокладки?
видимо IoDrvModbusTCPSlave. Сами же сказали


Дак выяснили же, что этот метод не работает
Ну с другой же работает - сами же сказали. Или не работает ?


В КДС3 нет возможности записать в %IW ни каким способом.
В оффлайне через IN_OUT или указатель пишется. Онлайн проверить нет возможности.

@ND
21.03.2016, 06:07
В оффлайне через IN_OUT или указатель пишется. Онлайн проверить нет возможности.

В онлайне не пишется.


Ну с другой же работает - сами же сказали. Или не работает ?
С другой - работает.

Валенок
21.03.2016, 11:46
"не пишется .. работает .."
Конечная задача - решена ?

Как понял задачу :
Хранить уставки где-то в своем кармане, но дать возможность внешнему мастеру их править

@ND
21.03.2016, 12:10
Конечная задача - решена ?
Я же выше писал, конечная задача решена.


Как понял задачу :
Хранить уставки где-то в своем кармане, но дать возможность внешнему мастеру их править
Именно так.

Валенок
21.03.2016, 12:23
С решением могу поздравить.
Но вот ни фига не понял как решили ))

@ND
21.03.2016, 12:51
С решением могу поздравить.
Но вот ни фига не понял как решили ))

))))

Библиотека (IoDrvModbusTCPSlave), которую по умолчанию рекомендует овен в своей документации ведёт обмен данными через %IW, %QW.
Поэтому данную задачу с помощью этой библиотеки решить невозможно, потому как невозможно что то записать в %IW самим контроллером, как ни крути.

А потом я обнаружил, что есть ещё библиотека (ModbusTCPSlave), в которой нет такой жёсткой привязки к %IW, точнее там вообще ты сам выбираешь место, куда будут попадать данные с помощью указателя.
Просто обнаружил это я достаточно поздно, в п #39. Там я сделал указатель на глобальную RETAIN переменную.
23270