Страница 1 из 4 123 ... ПоследняяПоследняя
Показано с 1 по 10 из 39

Тема: Имитация модулей ввода-вывода для удобной отладки

  1. #1

    По умолчанию Имитация модулей ввода-вывода для удобной отладки

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

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

    Отсюда вопрос: какой общий порядок действий должен быть?
    Я создал проект СПК107, там создал модбас девайс, прописал ему адрес как у реального модуля, регистры, вроде бы, прописал.
    Через эмулятор компортов создал связать двух виртуальных ком-портов.
    Запустил два виртуальных контролёра:
    1) с моим рабочим проектом
    2) с модбас девайсом этим

    Симулятор ком-портов увидел, что к нему подключены два устройства.
    Но модуль ввода Овена в моём проекте не загорается зелёным даже. Адреса прописаны верно, скорости выставлены одинаково.

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

    Или вообще вся эта эпопея обречена на провал по каким-то причинам, до которых я ещё не успел дойти?
    Заранее спасибо за подсказки

  2. #2

    По умолчанию

    Не очень понятна цель:
    Если нужно отладить связь или устранить проблему - то лучше использовать реальные модули.
    Для отладки алгоритма проще сделать блок эмуляции нужных значений внутри программы, отключив опрос модулей

  3. #3

    По умолчанию

    Гораздо удобнее для этих целей использовать ОРС сервер, например MasterOPC Universal Modbus Server,
    может быть слейвом, можно назначить нужные адреса регистров и задать любые значения. Проверить обмен по ТСР и RS485 с любым адресом слейва.
    Последний раз редактировалось kondor3000; 03.04.2025 в 09:40.

  4. #4

    По умолчанию

    Цитата Сообщение от Нидвораич Посмотреть сообщение
    Может, для успешного соединения обязательно нужно корректно прописать регистры в имитируемом устройстве?
    Ну вообще надо. Возможно даже буфер обмена посмотреть и понять, в чем проблема

  5. #5
    Пользователь
    Регистрация
    27.11.2011
    Адрес
    Краснодар
    Сообщений
    12,338

    По умолчанию

    Можно написать в RapidScada и привязывать к ее каналам. Язык C#. могу поделиться модулем (он до конца не дописан, но уже работоспособен) для запуска программ. Имитирует работу ПЛК (ну или если разобраться чего угодно)...

    Есть у разработчика платный Modbus slave. Если нужен именно Овен протокол, надо писать (нету, да и нужен ли?)...

    з.ы. модуль не тот, про который эти доки https://drive.google.com/drive/folde...Ft782RbUPfzFTa но суть та же. Называться будет ModSoftPlc, стоить будет дешевле, а базовая версия Free (будут некоторые ограничения)
    Тут можно посмотреть как выглядит программа https://github.com/Manjey73/ModFarm_...ed/ProgramZ.cs

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

  6. #6

    По умолчанию

    Снимок.PNG
    Можно так делать.
    М10.0 - включен режим эмуляции входов.
    Работает на S7-1200 S7-1500 S7-200 SMART(скрин с него).
    Последний раз редактировалось AlexandrGr; 03.04.2025 в 18:59.

  7. #7
    Пользователь
    Регистрация
    23.09.2008
    Адрес
    Центророссийск
    Сообщений
    2,861

    По умолчанию

    Если про rs485 110й то двумя скрепками соединить Rs1 и Rs2, наколотить нужных слейвов, вот и вся эмуляция
    С tcp да, не прокатит, нет петлевого интерфейса. Но другой ПЛК, а остальное тоже самое

  8. #8

    По умолчанию Решено для моего случая. Но для себя - читайте пост ниже

    Спасибо всем за ответы. Я почему-то не увидел, что тему уже опубликовали. И сам уже себе помог )
    Более суток ковырял эту тему, разобрался с регистрами и прочим.
    Модуль ввода не подключался по причине того, что он хочет запросить в сумме 29 слов, а я создавал устройство слейва, где не было столько регистров.
    Модулю вывода для счастливой жизни достаточно всего одного регистра, потому он и работал без проблем.

    Ещё раз поясню мои мучения:
    У меня семь контакторов шнеков управляются по показаниям весов. Для отладки мне надо имитировать ответ контактора о замыкании, вовремя тыкать туда-сюда эти самые контакторы, плюс имитировать процесс увеличения веса...
    Вручную это делать очень неприятно и сложно.
    Приходится загрублять все тайминги, чтоб успевать руками нащёлкать нужные состояния в MasterOPC Universal Modbus Server (естественно, я про него знаю).
    Но при загрублении таймингов сильно уходят показания измеряемой скорости насыпания. Плюс - я постоянно в голове держу не отладку, а порядок тыкания кнопочек.
    У меня было открыто три окна:
    Кодесис с отлаживаемым проектом.
    Кодесис с имитацией весового модуля.
    Модбас этот описи сервер универсал с имитацией модулей через теги.

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

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

    В общем и целом - я набрёл на ФБ OCL.MB_SerialSlave, который в коде, без лишних бубнов поднимает слэйв устройство. Опять же - на одном порту две штуки поднять нельзя, но можно сделать так, чтоб этот слэйв отзывался на любой ID. А дальше мне тупо повезло, что в двух моих модулях не пересекаются адреса хранения данных о состоянии выходов.
    Соответсвенно - по наводке Евгения Кислова я просто завёл слэйв с общим адресным пространством для обоих своих модулей.
    И вот щас всё работает. Теперь я в этот же проект могу добавить свой имитатор весового модуля, чтоб он сам включался по выходам модуля вывода. И ответку контакторов я теперь тоже могу автоматизировать, а не руками тыкать, поглядывая в таблицу на соответствие контакторов и выводов... И расположить все кнопки управления я теперь тоже могу так, как они физически на заводе стоят, а не в столбик из этих тегов в этом модбас матьего описи сервере)


    Если кому интересно - вот код с максимально подробным описанием:


    Код:
    (* 	ДИСКЛЕЙМЕР.
    	Спасибо Евгению Кислову за пинок в нужное время в нужном направлении :)
    
    	Работа примера основана на примере  5.9.2 из документа 
    	CODESYS V3.5 Настройка обмена по протоколу Modbus Руководство пользователя 04.08.2023 версия 3.2
    	Под шаблоном я буду иметь в виду готовый шаблон Модбас устройства от компании Овен.
    	
    	ОБРАЩАЮ ВНИМАНИЕ!!!!!!! Весь этот финт ушами с двумя слейвами одовременно возможен лишь потому, что
    	конкретно у этих двух приборов не пересекаются адреса хранения состояний выходов.
    	Если адреса пересекаются - то нужно будет определять, какое устройство сейчас долбится к нам за данными
    	и класть в буфер данные для СЛЕДУЮЩЕГО по адресу устройства. Потому что ФБ выдаёт адрес устройства, которому уже всё отдал.
    	По словам Евгения - мастер опрашивает устройства по порядку, так что можно нахитрить в этом направлении.
    	Примерный алгоритм: составляем массив адресов своих устройств, на первой итерации баним их всех, чтоб не отдать кому-то не то.
    	Запоминаем, кто к нам долбится, смещаемся по своему массиву вправо от полученного адреса и кладём в буфер нужные СЛЕДУЮЩЕМУ устройству данные.
    	Разбаниваем все устройства, работаем. Но это прокатит только если между адресами имитируемых устройств нет адресов реальных устройств. 
    	Иначе всё собъётся. Короче, к сути.
    	
    	В примере реализован функционал имитации работы модуля ввода MV110_16_D_DN и модуля вывода МУ110-16R_K
    	Эти два названия я взял из названий готовых шаблонов модулей из пакета от Овена.
    	По факту у меня дискретные приборы, и меня интересовали лишь две возможности для отладки:
    	1) для модуля вывода - заиметь на визуализации лампочку, которая загоралась бы, когда выход модуля активен
    	2) иметь на визуализации кнопку, по нажатию которой имитируется замыкание входа модуля ввода.
    	
    	Счётчики, ШИМы, показания датчиков мне не нужны, поэтому в этом примере они не реализованы. Но по идее - частично обработать инфу возможно.
    	
    *)
    PROGRAM PLC_PRG
    VAR 
    		fbComControl: 			OCL.COM_Control;	// ФБ управления портом COM1
    		fbModbusSerialSlave: 	OCL.MB_SerialSlave; // ФБ для реализиации модуля вЫвода
    		usiID:					USINT;
    (*  Чо ваще тут происходит
    	в ходе экспериментов выяснилось, что шаблон модуля ввода MV110_16_D_DN работает только в случае, когда под него выделено не менее 29 байт:
    	см.инструкцию от модуля, "Таблица А1 - Регистры Modbus".
    	Он опрашивает регистр с адресом 51, забирая оттуда битовую маску значений входов. Это как раз одно слово для 16 входов.
    	И ещё ему ну прям никак не обойтисть без доступа к регистрам с адресами 64..79, откуда он берёт значения счётчиков импульсов.
    	Мне они не нужны, но без выделения под них памяти ничего не работает (имитируемый модуль висит в офлайн или мигает туда-сюда в попытках подключения).
    	Так как регисты в памяти должы быть расположены последоватьельно - нужно будет выделить 79-51+1=29 слов памяти.
    	(+1 - потому что 2-1=1, но по факту количество 2) 
    	Шаблон модуля вЫвода MV110_16_D_DN прекрасно работает при одном выделенном для него слове.
    	Повторю - меня инстересует только состояние дискретных выходов, поэтому минимально необходимое количество WORD для моего случая = 1.
    	Насколько я понял - считывание состояния происходит с того же регистра (могу ошибаться). 
    	
    	Итого мы имеем: шаблон ввода хочет иметь дело с регистром 50 (1 шт). Шаблон вывода - с регистрами 51-79 (29 шт).
    	На самом деле - на данном этапе адресация регистров не важна. Важно именно их количество. В моём случае 30 шт.
    	
    	Везение заключается в том, что у двух этих модулей не пересекаются адреса нужных нам регистров.
    	Соответственно - их можно расположить в памяти в таком порядке:
    	IN - это будет регист модуля ввода
    	IN01..16 - регистры счётчиков модуля ввода, без которых он жить не может
    	OUT - регист модуля вывода. 
    	
    	01	OUT
    	02	IN
    	03
    	04
    	05
    	06
    	07
    	08
    	09
    	10
    	11
    	12
    	13
    	14
    	15	IN01
    	16	IN02
    	17	IN03
    	18	IN04
    	19	IN05
    	20	IN06
    	21	IN07
    	22	IN08
    	23	IN09
    	24	IN10
    	25	IN11
    	26	IN12
    	27	IN13
    	28	IN14
    	29	IN15
    	30	IN16
    	Чтобы не путаться с нулевой адресацией и количеством - адресацию массива данных я буду начинать от 1, а не от 0.
    
    *)
    
    awSlaveData:				ARRAY [1..30] OF WORD; // буфер данных Modbus Slave
    
    (* в моём случае это не нужно, потому что у меня нет регистров, которые читаются и пишутся обеими участниками обмена.
    	Если такое есть - нужно тут в коде писать данные в такие регистры не циклично, а по необходимости.
    	Иначе цикличная запись будет постоянно затирать принимаемую инфу. Так делать фу.
    	xWrite: 		BOOL; // команда записи данных из программы в регистры Modbus Slave
    	fbWriteEdge:	R_TRIG; // триггер для однократной записи
    *)
    axIN: ARRAY [1..16] OF BOOL;  // массив состояний входов модуля ввода. Привязаны к тумблерам
    axOUT: ARRAY [1..16] OF BOOL; // массив состояний выходов модуля вЫвода. Привязаны к лампочкам
    END_VAR





    // поднимаем COM порт с нужными настройками
    fbComControl
    (
    xEnable := TRUE,
    udiComPort := 33,
    udiBaudrate := 19200,
    udiByteSize := 8,
    eParity := OCL.COM_PARITY.EVEN,
    eStopBit := OCL.COM_STOPBIT.ONE
    );
    //запускаем слейва с адресом 255. Это позоляет ему отвечать на запрос с любым ID.
    fbModbusSerialSlave
    (
    (* насколько я понял - начальный адрес является обманом для опрашивающего устройства.
    Когда оно просит регистр с адресом 50 - мы ему подсовываем свой самый первый регистр,
    и все остаются довольны. То есть - это смещение адресации на уровне нашего кода тут.
    Если бы не было этого параметра - пришлось бы тут в коде создавать область памяти,
    в которой первые 49 слов банально не использовались бы.
    А так - у нас шаблон модуля вывода хочет видеть данные на 50 адресе,
    шаблон модуля ввода - на 51, и мы просто указываем смещение в 50:
    чтоб вместо 50 выдать то, что лежит у нас в первой ячейке, а вместо 51 - то, что во второй.
    50 51 64 ... 79 - шаблоны модулей думают, что читают по этим адресам
    OUT IN IN01 IN16 - вот эти данные
    1 2 15 30 - на самом деле - данные у нас лежат вот с такими индексами.
    *)
    c_uiStartAddr:=50,
    xEnable :=fbComControl.xActive,
    hCom := fbComControl.hCom,
    usiSlaveId := 255,
    pData := ADR(awSlaveData),
    szSize := SIZEOF(awSlaveData)
    );

    // сорян за хардкод Уже некогда разбираться с преобразованиями
    // в первой ячейке у нас лежат состояния вЫходов (которые обманным образом транслируются под видом регистра с адресом 50)
    axOUT[1]:=awSlaveData[1].0;
    axOUT[2]:=awSlaveData[1].1;
    axOUT[3]:=awSlaveData[1].2;
    axOUT[4]:=awSlaveData[1].3;
    axOUT[5]:=awSlaveData[1].4;
    axOUT[6]:=awSlaveData[1].5;
    axOUT[7]:=awSlaveData[1].6;
    axOUT[8]:=awSlaveData[1].7;
    axOUT[9]:=awSlaveData[1].8;
    axOUT[10]:=awSlaveData[1].9;
    axOUT[11]:=awSlaveData[1].10;
    axOUT[12]:=awSlaveData[1].11;
    axOUT[13]:=awSlaveData[1].12;
    axOUT[14]:=awSlaveData[1].13;
    axOUT[15]:=awSlaveData[1].14;
    axOUT[16]:=awSlaveData[1].15;

    // во второй - состояния входов

    awSlaveData[2].0:=axIn[1];
    awSlaveData[2].1:=axIn[2];
    awSlaveData[2].2:=axIn[3];
    awSlaveData[2].3:=axIn[4];
    awSlaveData[2].4:=axIn[5];
    awSlaveData[2].5:=axIn[6];
    awSlaveData[2].6:=axIn[7];
    awSlaveData[2].7:=axIn[8];
    awSlaveData[2].8:=axIn[9];
    awSlaveData[2].9:=axIn[10];
    awSlaveData[2].10:=axIn[11];
    awSlaveData[2].11:=axIn[12];
    awSlaveData[2].12:=axIn[13];
    awSlaveData[2].13:=axIn[14];
    awSlaveData[2].14:=axIn[15];
    awSlaveData[2].15:=axIn[16];
    Последний раз редактировалось Нидвораич; 04.04.2025 в 20:47.

  9. #9

    По умолчанию

    Цитата Сообщение от 1exan Посмотреть сообщение
    Не очень понятна цель:
    Если нужно отладить связь или устранить проблему - то лучше использовать реальные модули.
    Для отладки алгоритма проще сделать блок эмуляции нужных значений внутри программы, отключив опрос модулей
    Хотелось без переделок рабочего проекта сделать полную имитацию устройств. Я уже знаю, как в проекте понять, где он запущен - на рабочей железке или на виртуальном контролере.
    И да, знай бы я заранее, сколько гемора я хапну с этой имитацией - я бы так сделал - просто завёл бы ёщё одну визуализацию и повесил бы её на веб-морду. И со второго монитора тыкал бы всё, что мне нужно.
    Это реально проще и удобнее. Почему-то я упёрся рогом в имитацию работы по сети, и вот доупирался до результата

    Ну зато я покопался в Модбасе. Ещё позавчера для меня модбас и rs-485 представляли что-то одно и то же примерно ))
    Последний раз редактировалось Нидвораич; 04.04.2025 в 19:13. Причина: очепятки

  10. #10
    Пользователь
    Регистрация
    27.11.2011
    Адрес
    Краснодар
    Сообщений
    12,338

    По умолчанию

    Пока не изучал код.
    1. Так понимаю там привязка через шаблоны + использование каких-то fb. Ставить CodeSys 3 не планирую, своего Г хватает на компе.
    2. Каким образом вы создаете эмуляцию? все на виртуальных ПЛК CodeSys ? нужна работа по реальным COM портам? не помню, можно ли натравить виртуальный COM порт на другой виртуальный, не пробовал ни разу
    3. на COM порту должно быть несколько имитируемых устройств ?

    Если рисунком сделаете как хотите, чтобы понять можно ли это организовать на одном ПК.

    4. Что нужно от имитируемых устройств? ну например модуль вывода какой-нибудь MX110 или модуль ввода, или аналогового ввода ?
    5. какая нужна скорость работы модулей ?

    з.ы. давайте начнем с простого модуля, например вывода - марка/модель
    чтение маски выходов, запись выхода - что еще нужно? например какая видуализация? где ручное управление, где автоматическое?
    Последний раз редактировалось melky; 05.04.2025 в 11:01.

Страница 1 из 4 123 ... ПоследняяПоследняя

Похожие темы

  1. Отвалы модулей ввода/вывода.
    от FlameAtomicFox в разделе ПЛК2хх
    Ответов: 3
    Последнее сообщение: 03.02.2025, 07:16
  2. Ответов: 2
    Последнее сообщение: 21.03.2024, 08:17
  3. Подключение модулей ввода/вывода по Modbus RTU
    от известь в разделе Master SCADA 4D
    Ответов: 3
    Последнее сообщение: 13.12.2023, 08:41
  4. ПЛК160-24.А-М + 5 модулей ввода/вывода
    от des_na_laes@mail.ru в разделе Мх110
    Ответов: 25
    Последнее сообщение: 22.12.2020, 18:06
  5. ПЛК100+18 модулей ввода и вывода
    от Дулат в разделе Эксплуатация
    Ответов: 23
    Последнее сообщение: 08.11.2019, 11:52

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •