Объявление

Свернуть
Пока нет объявлений.

ModBusEx - ReadHoldRegsAsync

Свернуть
X
 
  • Фильтр
  • Время
  • Показать
Очистить всё
новые сообщения

  • ModBusEx - ReadHoldRegsAsync

    Доброго дня.
    Ранее для опроса ведомых устройств (4 единицы оборудования одного типа, и 4 единицы - другого типа), использовались стандартные устройства CDS, и опрос велся из дерева проекта. Контроль линий и отключение опроса устройства, с его последующим включением в цикл опроса доставлял неудобства.
    Было принято решение использовать программные средства для описания протокола из библиотеки ModBusEx.
    Стартовая программа для опроса 1 единственного устройства, 1 единственного регистра не вызвала каких либо проблем. Ошибок на выходе блока ReadHoldRegsAsync не получено, всё стабильно.
    Но вот пакеты данных, которые ПЛК получает от ведомого устройства вызывают некоторые подозрения.
    Как ив примере данные по ссылке пишутся в массив ErCodeSlave с элементами byte. Запрашиваем мы всего 1 регистр по адресу 16№4000 (16384). Заведомо известно что в данном регистре лежит значение 81 (или 16#51). Получается отправляем запрос, получаем ответ в размере 2 Byte (в ведомом устройстве word).
    В итоге при работе опроса на выходе в массиве получаем не 2 значения (младший и старший байты) а целый набор данных, который ещё и меняется от запроса к запросу.
    Что примечательно, блок ReadHoldRegsAsync на выходе в переменной ByteCnt так же выдаёт не 2 байта, а разные значения, то 8, то 7 байт данных, хотя должно быть 2 байта, так как регистр опрашиваем всего один.
    Нажмите на изображение для увеличения.   Название:	реальном времени.png  Просмотров:	0  Размер:	40.0 Кб  ID:	2194
    Подключившись к шине, и послушав, что происходит на ней с использованием Serial Port Monitor, замечено что и запрос от ПЛК, и ответ от устройства более чем логичный, и верный. В ответе 2 байта с 16#0051 (10#81)? что и должно быть!
    Нажмите на изображение для увеличения.   Название:	-запрос-ответ.png  Просмотров:	0  Размер:	20.0 Кб  ID:	2195
    Пока писал весь вопрос, понял, что в массив данных пишется весь запрос, а затем весь ответ. Включая и адрес устройства, и функцию, и начальный адрес, и количество считываемых байт.
    Получается из этого массива нужно будет ещё в определённый момент вычленить полученные данные, предполагаю что по восходящему фронту xComplete надо из текущего массива вытащить необходимые данные, и это легко если читается 1 регистр. для этого ещё надо выделить область памяти под структуру с нужным набором.... А если читается целая структура из разного набора данных? в общем сложно...
    Будет ли продолжение развития данного функционального блока, в том плане что я на выходе блока буду получать не набор данных, описывающих весь запрос и ответ, а только уже преобразованные конечные данные, например как это делает Овен в своей библиотеке OwenCommunication?
    Либо может есть возможность получить исходник ФБ ReadHoldRegsAsync, дабы допилить его на получение того, что мне нужно? Потому что обрабатывать каждый запрос из требуемых мне 120 штук (грубо) это то ещё удовольствие...

  • #2
    Вытащить то что необходимо получилось путём привязки массива и структуры с необходимым набором типов данных к одной области памяти, например MW100. Далее в момент когда количество считываемых байт равняется нужному нам количеству, а мы читаем 1 слово, значит 2 байта, в этот момент мы из структуры в MW100 данные копируем уже в другую структуру, но после этого ещё необходимо переставить байты местами. И вуаля, получаем то что нам необходимо.
    Но это всё опять же костыли, или просто разработчики библиотеки не хотят упростить жизнь своим пользователям😁
    По идее в функциональном блоке это бы всё внутри сделать, тогда на выходе мы получим уже готовый пакет, которому на выходе можно указать ссылку на структуру в глобальном списке, и CDS сделает всё за вас. Надо только будет с перестановкой байт и слов поиграть, но это уже не проблема.
    Вложения

    Комментарий


    • #3
      После ещё пары попыток допинать до чего-то простого получилось так:

      Нажмите на изображение для увеличения.   Название:	экрана 2024-12-18 164239.png  Просмотров:	0  Размер:	10.5 Кб  ID:	2199

      И в требуемой структуре уже получаем не набор байт, а полноценное слово, которое лежит в ведомом устройстве.

      В общем, было бы здорово получить исходники библиотечных блоков, чтобы их допинать под себя!
      Последний раз редактировалось Дмитрий Васяев; 18-12-2024, 11:53 AM.

      Комментарий


      • #4
        Сообщение от Дмитрий Васяев Посмотреть сообщение
        После ещё пары попыток допинать до чего-то простого получилось так:

        Нажмите на изображение для увеличения.   Название:	экрана 2024-12-18 164239.png  Просмотров:	4  Размер:	10.5 Кб  ID:	2199

        И в требуемой структуре уже получаем не набор байт, а полноценное слово, которое лежит в ведомом устройстве.
        Приветствую, для получения данных после запроса , передайте в pData приемный буфер tmpbuf: array [ 0 .. 255 ] of byte;

        Например вот так

        ReadHoldRegs( xEnable := true, Mode := EnModbusMode.RTU, SlaveId := 1, StartAddr := 1, Quantity := 10, Handle := serial.Handle, TimeOut := timeout, pData := adr( tmpbuf ), xComplete => xDone, Exception => ex, ByteCnt => nBytes );



        Далее путем смещения по буферу извлекаем нужные данные.

        case ex of

        EnModbusException.Success:


        //чтение значения 1 регистра

        wRegValue1 := Mem.PackBytesToWord( tmpbuf[0], tmpbuf[1] );

        //чтение значения 2 регистра

        wRegValue2 := Mem.PackBytesToWord( tmpbuf[2], tmpbuf[3] );

        //чтение значения 3 регистра

        wRegValue3 := Mem.PackBytesToWord( tmpbuf[4], tmpbuf[5] );

        //чтение значения 4 регистра

        wRegValue4 := Mem.PackBytesToWord( tmpbuf[6], tmpbuf[7] );


        EnModbusException.TimeoutError:

        readAI := Errors.ERR_TIMEOUT;

        else

        readAI := Errors.ERR_EXCEPTION;

        end_case


        и так далее, путем смещения по tmpbuf извлекаем нужные данные.

        Комментарий


        • #5
          Тоже вариант конечно, но мой вараинт мне кажется проще)
          К тому же я попробовал парсить пакеты по условию "reqKU1.Exception=EnModbusException.Succes", и в конечных тегах всё равно выдаётся и запрос и ответ...

          Комментарий


          • #6
            В общем бился я с этим делом, бился... Ещё раз проверил попытку извлечения данных по условию EnModbusException.Success, при срабатывании условия извлекались данные из области памяти в требуемые переменные. Но всё равно получал я не только то что хотел увидеть, но и куски посылки запроса и ответа (так как я читаю word значения, то 81 менялись с 259 (16#103, а посылка такая - 01 03 40 00 00 01 CRC).
            Я бы мог вам отправить исходник и файл для ПО ModBus Slave.
            Опрос я веду не группы регистров, а каждого по отдельности, так как во первых - ведомое устройство просто не поддерживает групповой опрос, а во вторых - все регистры в разных местах... И получается совершенно абракадабра в выходном списке глоб. переменных. То есть там и есть то что я хочу, а это заведомо известно, но эти данные постоянно меняются с кусками посылок. Успех в получении требуемого был только при условии проверки не Esceprion Code, d сравнения количества считываемых данных.... Как в постах выше...
            Параллельно вопрос, обязательно ли закрывать порт после успешного чтения одного регистра, и потом на следующем чтении опять его открывать?

            Комментарий


            • #7
              Сообщение от Дмитрий Васяев Посмотреть сообщение
              В общем бился я с этим делом, бился... Ещё раз проверил попытку извлечения данных по условию EnModbusException.Success, при срабатывании условия извлекались данные из области памяти в требуемые переменные. Но всё равно получал я не только то что хотел увидеть, но и куски посылки запроса и ответа (так как я читаю word значения, то 81 менялись с 259 (16#103, а посылка такая - 01 03 40 00 00 01 CRC).
              Я бы мог вам отправить исходник и файл для ПО ModBus Slave.
              Опрос я веду не группы регистров, а каждого по отдельности, так как во первых - ведомое устройство просто не поддерживает групповой опрос, а во вторых - все регистры в разных местах... И получается совершенно абракадабра в выходном списке глоб. переменных. То есть там и есть то что я хочу, а это заведомо известно, но эти данные постоянно меняются с кусками посылок. Успех в получении требуемого был только при условии проверки не Esceprion Code, d сравнения количества считываемых данных.... Как в постах выше...
              Параллельно вопрос, обязательно ли закрывать порт после успешного чтения одного регистра, и потом на следующем чтении опять его открывать?
              в биб-ке уже реализовано отсеивание данных запроса и функции в пакете, в приемный буфер возвращаются только данные регистров, пробовали вытащить данные как я выше писал? Тем более Вы всего один запрос отправляете , как я понял, а не групповой

              Комментарий


              • #8
                я позже могу сделать простой пример чтения и извлечения и прикрепить его сюда. Какую версию биб-к используете?

                Комментарий


                • #9
                  Может быть и правда у меня что не то с версиями, потому что с ними ноги сломать можно...
                  Как вы писали, так я и делал. Почти. смысл остался тот же самый, условие - одинаковое.
                  CDS 3.5.14.40
                  библиотеки взяты с вашего FTP-сервера:
                  Нажмите на изображение для увеличения. 

Название:	экрана 2024-12-19 125312.png 
Просмотров:	32 
Размер:	68.5 Кб 
ID:	2206
                  Что касается компилятора проекта:
                  3.5.14.40 (с 3.5.14.10 разницы никакой не наблюдал)
                  Что касается репозитария:
                  Library Agava PLC 3.5.10.20 (что примечательно, скачана 3.5.10.21, но ставится она как 3.5.10.20)

                  Комментарий


                  • #10
                    Сообщение от Дмитрий Васяев Посмотреть сообщение
                    Может быть и правда у меня что не то с версиями, потому что с ними ноги сломать можно...
                    Как вы писали, так я и делал. Почти. смысл остался тот же самый, условие - одинаковое.
                    CDS 3.5.14.40
                    библиотеки взяты с вашего FTP-сервера:
                    Нажмите на изображение для увеличения. 

Название:	экрана 2024-12-19 125312.png 
Просмотров:	32 
Размер:	68.5 Кб 
ID:	2206
                    Что касается компилятора проекта:
                    3.5.14.40 (с 3.5.14.10 разницы никакой не наблюдал)
                    Что касается репозитария:
                    Library Agava PLC 3.5.10.20 (что примечательно, скачана 3.5.10.21, но ставится она как 3.5.10.20)
                    Хорошо, я сегодня перепроверю работу биб-ки , дам ответ.

                    Комментарий


                    • #11
                      Сообщение от Пушкарев Андрей Посмотреть сообщение

                      Хорошо, я сегодня перепроверю работу биб-ки , дам ответ.
                      Доброго, получилось проверить работу ФБ?

                      Комментарий


                      • #12
                        Сообщение от Дмитрий Васяев Посмотреть сообщение

                        Доброго, получилось проверить работу ФБ?
                        Добрый день, да проверил, все работает. Пример прикрепил. В примере читал регистры с 0 по 5, значения читал в буфер.
                        Вложения

                        Комментарий


                        • #13
                          Загрузил ваш пример, сначала тоже не запустился. Сбросил устройство. Залил по новой - заработало.
                          Соответственно написал на основе вашего кода свой, для 1 ведомого устройства - всё работает. Написал для 2го ведомого устройства - работает. Но только по отдельности. Точнее пока в сети 1 ведомое устройство из двух, неважно какое. Как только на шине 2 ведомых устройства и больше, шина ложится. И это касается не только самописного опроса. Загрузили старый проект, где опрос идёт из дерева проекта, там ровно такая же ситуация!
                          Может это вопрос конкретно в опрашиваемых устройствах, хотя мы уже выпустили не мало шкафов, где опрашивали до 8 подобных устройств. Магия, не иначе...
                          Вопрос следующий. Мы расположены недалеко, в Челябинске. Появилась идея приехать к вам в гости на производство в следующем году, в январе может быть, со своим оборудованием, и со своим ПЛК-40. И может вы нам сможете открыть глаза на происходящие в данной ситуации? Заодно поделились бы опытом!

                          Комментарий


                          • #14
                            Сообщение от Дмитрий Васяев Посмотреть сообщение
                            Загрузил ваш пример, сначала тоже не запустился. Сбросил устройство. Залил по новой - заработало.
                            Соответственно написал на основе вашего кода свой, для 1 ведомого устройства - всё работает. Написал для 2го ведомого устройства - работает. Но только по отдельности. Точнее пока в сети 1 ведомое устройство из двух, неважно какое. Как только на шине 2 ведомых устройства и больше, шина ложится. И это касается не только самописного опроса. Загрузили старый проект, где опрос идёт из дерева проекта, там ровно такая же ситуация!
                            Может это вопрос конкретно в опрашиваемых устройствах, хотя мы уже выпустили не мало шкафов, где опрашивали до 8 подобных устройств. Магия, не иначе...
                            Вопрос следующий. Мы расположены недалеко, в Челябинске. Появилась идея приехать к вам в гости на производство в следующем году, в январе может быть, со своим оборудованием, и со своим ПЛК-40. И может вы нам сможете открыть глаза на происходящие в данной ситуации? Заодно поделились бы опытом!
                            напишите какие регистры читаете у слейва, количество слейвов с адресами, я в эмуляции запущу проверю этот момент.

                            Комментарий


                            • #15
                              На практике мы не однократно встречались с приборами которые не верно отвечают, т.е они отвечают на запросы которые им не предназначены изначально, проверяется это лего. Возьмите например modbus poll , и сделайте там тоже самое по опросу, если увидите ошибки, значит с приборами что то не так.

                              Комментарий

                              Обработка...
                              X