Просмотр полной версии : PLC110 modbus.lib MV110-8AC
Добрый день уважаемые эксперты! Осваиваю библиотеку modbus.lib. Задача подключить к PLC110 8 шт. MV110-8AC. Пытаюсь подключить пока один. Делал проект согласно примера но на MV110-8A. Просмотрел несколько примеров (немного отличающихся по структуре), несколько раз переделывал, искал ошибки - все равно не получается. Если кому не сложно наставить на путь истинный, буду премного благодарен.
P.S. Проект реальный не ради интереса, оборудование имеется, проект не коммерческий, исключительно для своего предприятия.
А что конкретно не получается то? У Вас в проекте меня смущают настройки порта (всё по нулям, кроме скорости). И пересобираете байты по-моему неправильно (но не утверждаю, мельком глянул), вроде там регистры флоат идут подряд начиная с 0х0120
Евгений Дударев
16.06.2016, 17:26
Если я не ошибаюсь, то сегодня я уже ответил GTS на почту. Дело в том, что Вы перепутали количество регистров и байтов. Вам нужно читать не 112 регистров, в двое меньше.
Попробуйте опросить для начала word-значения, потом переходите к Float
Если я не ошибаюсь, то сегодня я уже ответил GTS на почту. Дело в том, что Вы перепутали количество регистров и байтов. Вам нужно читать не 112 регистров, в двое меньше.
Попробуйте опросить для начала word-значения, потом переходите к Float
Кстати да, тоже обратил внимание на 112 регистров, забыл указать
Спасибо за ответ, завтра попробую. С регистрами маху дал. Да Евгений это я вам на почту писал, не знал что вы эту ветку курируете, а то бы не стал отвлекать. По поводу регистров, считываю все потому что в примере так было сделано. Решил сделать ближе к оригиналу. По поводу считывать один регистр, пробовал, причём все по очереди - получал ерунду. Вообще мне нужны значения в real и ошибки. Float в 8АС отличается от 8А, в первом 3 регистра, во втором 2. Евгений Вам лучше сюда писать или также на почту?
Валенок, огромное спасибо, буду разбираться.
Валенок, у Вас в проекте есть несколько POU, которые я нашел когда производил компиляцию и выскочила ошибка. Простите за глупый вопрос, как и где вы их прописали, не могу найти.
на скрине же нет ошибки, а если Вы про то где лежит такой тип данных, то ищите вкладку с пользовательскими типами данных
Нет ошибки потому что исправил. Хотел просто узнать где это находится. В проекте Валенка все что до буфера понимаю, а как он преобразует из буфера уже нет, MV8AC(FB) вообще не пойму.
Валенок, он такой :) , загадочный
попробуйте его проект экспортировать в файл, выбрав все пункты, в нем будет легче найти не достающие звенья
Вопрос не в копировании. а понятии структуры. Я думаю для начала попроще преобразовывать данные из буфера, как в примере, но не получается блин.
я присоединяюсь к Валенку о месте роста рук, очень неудобно структуру создавать, но Валенок же написал, я так понимаю ей уже пользоваться можно, а не понимать
И если кому то что то не понятно, то начинать надо с http://www.owen.ru/uploads/re_mv110-8ac_2113.pdf страницы 57
Простите о месте роста рук не понял. К сожалению не работает. Тот мануал который Вы указали открыт постоянно. Чем мне поможет страница 57?:
Г.3.4 Считывание версии программы прибора
Посылка: $AAF[CHK](cr),
где АА – адрес модуля, от 00 до FF,
[CHK] – контрольная сумма,
(cr) – символ перевода строки (0х0D).
Ответ: !АА(версия(7 символов))[CHK](cr).
Пример – !ААVx.yy[CHK](cr).
При запросе данных с несуществующего канала выдается ответ ?AA[CHK](cr).
При синтаксической ошибке или ошибке в контрольной сумме не выдается никакого ответа.
Прошу прощения у нас мануалы разных версий. с указанной Вами таблицей знаком. Вопрос как преобразовать из буфера данные в real и word?
ptr_byte:=ADR(srd1);
ptr_byte^:=buffer[7];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[6];
ptr_byte:=ADR(real1);
ptr_byte^:=buffer[13];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[12];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[11];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[10];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[9];
ptr_byte:=ptr_byte+1;
ptr_byte^:=buffer[8];
Так верно?
как верно можно сказать только имея прибор на руках, обычно байты требуется менять,но может и словами можно ограничится.
.. К сожалению не работает..
Да ладно. Значит чего-то вокруг не так напилили. У меня несколько лет именно так* работает.
(*в смысле обработки данных, а не обмена)
В Индию больше не пойду. Напилил вот что.
Глянул на сам обмен. Взяли за основу очень корявый пример.
В конфигураторе для 8АС, rs.dl = ?
Ну пример какой был. Пример в 12 посту.
"В конфигураторе для 8АС, rs.dl = ?" - это о чем простите не понял.
Пример коряв.
rs.dl - один из параметров настройки в конфигураторе модуля
0 - отл. зачем нужно 45, когда речь про модбас - все равно никто внятно не объяснит.
Почему пример коряв ? Зачем-то 2 автомата + куча внешних if'ов.
Modbus.lib давно не юзал (обхожусь одним syslibcom'ом), но насколько помню поведение enable нужно толчковое - передним фронтом запустили блок обмена - и дальше скинули enable.
Спасибо, в понедельник попробую. Что за автомат, простите за глупый вопрос?
Добрый день уважаемые господа! Толи лыжи не едут, толи я такой невезучий. Скинул контроллер, очистил все в проекте, загрузил, опять показывает ерунду. 8 канал.
Подключил один канал через конфигуратор, Работает.
Уважаемый Валенок можно получить коментарии построчно в ФБ MV8AC кратко.
Кто нибудь может подсказать как из буфера "вытащить байты, перевернуть"- что бы получить real? В 8АС 3 регистра под Float как быть в этом случае?
Кто нибудь может подсказать как из буфера "вытащить байты, перевернуть"- что бы получить real? В 8АС 3 регистра под Float как быть в этом случае?
так Вы внимательно прочтите, там в трех регистрах флоат(IEEE754)два регистра и плюсом одно слово метки времени
Как из буфера получить real? Переместить последний байт на первый? Пример который мне предоставили Вам не понравился, выше я написал что ФБ Валенка я не понял. Есть простой понятный пример?
Выложи то что грузишь (1:1), настройки 8АС
На линии есть еще кто-нить кроме 8АС и ПЛК ?
Уважаемый Валенок можно получить коментарии построчно в ФБ MV8AC кратко.
Там же они есть 8( ?
Проект во вложении. Настройки 8АС стандартные 115200 8n1 adress = 21, задерка 0. На этой линии ничего больше нет.
Подключил один канал через конфигуратор, Работает.
Через конфигуратор работает же!
Мне положить на конфигуратор
За основу вы где-то или качнули реальный мусор или что-то пропустили. Вот и разбирайтесь как это работает, например :
1.Из-за строки 55 можете выкинуть строки 21..22, 46,49, 54..57 как рукоблудие.
2.Из-за строки 23 можете выкинуть enable, и передать в блок_обмена.enable вечный true (именно так работает этот кусок мусора, выкинуть строки 23,47 а после прочитать пост #23
3.Ошибок обработки данных у меня - нет. Разбирайтесь с окружением (выше)
Я извиняю Валенок, но пример на основе которого я сделал, Ваш. Откуда мусор! Это конечно верх наглости с моей стороны, но я допилил Ваш проект, там где Вы указали в коментах! Сейчас буду разбираться, но может быть дело в регистрах всетаки?
Ну говорю же - пропустили.
Забудьте эти мутные слова - регистр, буфер. Есть структуры - исходные и конечные.
Исходные - это и есть таблица регистров. Конечные - это то, с чем можно нормально работать в конкретной среде.
Иногда (редко) они совпадают. Для 8AC - нет. Блок MV8AC - это приведение исходной структуры к конечной.
Исходная здесь - это непрерывно расположенная в памяти область {SRD, Read - см.карту в РЭ}.
Но ! Это же модбас (как протокол), у него свой сетевой порядок байт. А modbus.lib (как биб-ка) работает нормально, но не допилена до нормального использования (я ее не юзаю).
Почему не допилена ? Потому что сетевой порядок байт протокола модбас относится к порядку байт приборов овен как 2143/1234, а процедура "тудой/сюдой" не впендюрена в саму б-ку.
В данном случае по получению данных от прибора их еще нужно привести к исходному виду, например :
var
pw : pointer to array[1..32] of word;
......
pw := adr(MV8AC.SRD);
for i := 1 to 32 do //получение исходной структуры из сетевого набора байт
pw^[i] := rol(pw^[i],8);
end_if
MV8AC(); //а вот теперь из исходной {SRD,Read} => конечную {Ai}
И я бы принципиально не стал делать в одном проходе из сетевого набора байт конечную структуру
Почему руки афтора таблицы растут не из плеч ? Потому-что в подавляющем большинстве случаев модули опрашиваются контроллерами Овен (хотя модули и не привязаны к овену) а таблицы рег-ов желательно привязывать к формату. C учетом выравнивания в 8AC/2AC это невозможно.
Я уж молчу про общее несоответствие ВСЕХ овен-модулей с данными размером в 4 байта порядку данных любого овен-плк.Порядок данных не специфицирован в протоколе ? Дык замечательно - сопоставили б сразу данные в связке плк/модули. Но поезд ушел.
Спасибо, буду пробовать разобраться, хотя не все понятно.
Добрый день уважаемы господа! Опрос модуля 8АС по real и srd получился (причем по всем 8 входам). Если кому то интересно выложу проект. Теперь задача стоит опрашивать 6 модулей 8АС. Но выяснилась небольшая особенность: если физически отключить модуль от ПЛК, то последние значения real и srd сохраняются, ошибка err в modbus.lib =0, а complete (признак завершения операции) постоянно переключается False на True, как будто модуль продолжает опрашиваться.
Вы уверены, что ошибка =0? Я точно помню видел при физическом отключении 255. Может просто не успеваете глазами увидеть? Попробуйте записывать в какой-нибудь массив все значения отличные от нуля для проверки.
P.S. Каюсь, вспомнил, что ошибку я видел в библиотеке к CDS 3.5, но всё равно, не может же быть, что висит 0 при отключении
Добрый день. Нет 0 не висит, постоянно переключается с 0 на 255. Но complete (признак завершения операции) постоянно переключается False на True, как будто модуль продолжает опрашиваться. И значения real сохраняются последние и не сбрасываются.
При наличии ошибки 255 вы их просто принудительно обнуляйте или присваивайте какие вам нужно значения
Это я понял, но почему 255 не постоянно, а переключается на 0 переодически.
Не могу сказать, это лучше у разработчиков библиотеки уточнить
Добрый день. Вопрос ко всем кто использует библиотеку: Если физически отключить RS-485, err (ошибка modbus) постоянно переключается с 0 на 255, и complete (признак завершения операции) постоянно переключается False на True, как будто модуль продолжает опрашиваться - так должно быть или что-то не верно в примере?
Подчистил для Воронежа, но не настаиваю на единственном способе
Валенок очень понравился ваш вариант, изящно и красиво. Решил убрать у себя все эти "индии" и начал опробовать на модуле 2АС. В ФБ изменил:
FUNCTION_BLOCK (*строго ФБ ...*) MV2AC
(*(C) Валенок*)
VAR_OUTPUT
Ai : ARRAY[1..2] OF MV_2AC;
END_VAR
VAR
(*читаем 8 регистров за раз с адреса 16#106*)
SRD : ARRAY[1..2] OF WORD;
READ : ARRAY[1..2,1..3] OF WORD;
x : ARRAY[1..240] OF BYTE; (*просто добил буфер до 256 байт*)
(*!*)
i : INT;
p : POINTER TO ARRAY[1..2] OF WORD;
END_VAR
---------------------------------------------------------------------------
FOR i := 1 TO 2 DO
Ai[i].Status := SRD[i];
Ai[i].Cyclic := Read[i,3];
p := ADR(Ai[i].Value);
p^[1] := Read[i,2];
p^[2] := Read[i,1];
END_FOR
Структуру оставил как есть
TYPE MV_2AC :
STRUCT
Status :ENUM_STATUS := STATUS_UNREADY;
Cyclic :WORD;
Value :REAL;
END_STRUCT
END_TYPE
В программе соответственно:
CASE state OF
0:
enable:=1;
(* функция 03 флоат - ФБ считывает значение параметров *)
PBuffer := ADR(MV2AC.SRD);
get3_modbus(
Enable:=enable, (* разрешение работы блока *)
Mode:=MB_RTU , (* режим передачи*)
DevAddr:=40 , (* адрес*)
FirstAddr:= (*16#106*)262, (* номер регистра*)
Quantity:=8, (* количество регистров*)
ComHandle:=Settings.Port , (* номер COM-порта*)
TimeOut:=TimeOut , (* таймаут *)
Buffer:= PBuffer^ , (*Buffer,*) (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера, формируем переменные*)
MV2AC;
IF MV2AC.Ai[1].Status <>0 THEN errAi1:=TRUE; ai1 := 0; ELSE errAi1:=FALSE; ai1 := MV2AC.Ai[1].Value; END_IF;
ai1w := REAL_TO_WORD (ai1);
IF MV2AC.Ai[2].Status <>0 THEN errAi2:=TRUE; ai2 := 0; ELSE errAi2:=TRUE; ai2 := MV2AC.Ai[2].Value; END_IF;
state:=1;
enable:=0;
ELSE
state:=1;
END_IF
END_IF
1:
state:=0;
END_CASE
Но значения получаю неправильные (что-то там в -30 или т.п. степени). Через "индию" всё норм, но некрасиво :(.
Что-то подсказывает мне, что в ФБ что-то неправильно, но что не пойму, карта регистров 2ас и 8ас вроде как совпадает (только количеством каналов отличается) :confused:.
Не подскажете что не так?
Спасибо, так заработало. Только бы въехать в назначение функции...(((
Как я понял функция - аналог кода в 37 посте:
var
pw : pointer to array[1..32] of word;
......
pw := adr(MV8AC.SRD);
for i := 1 to 32 do //получение исходной структуры из сетевого набора байт
pw^[i] := rol(pw^[i],8);
end_if
Что мне непонятно это присвоение pw, да и PBuffer ADR(MV8AC.SRD). Почему не ADR(MV8AC)?
И по идее нормально будет работать на 2А, 8А модулях
В таком виде мне понятно, что происходит, не уверен, что код корректный, но данные обрабатывает правильно:
SysMemCpy(ADR(MV2AC),ADR(Buffer),16);
pw := ADR(MV2AC);
FOR j := 1 TO 8 DO (*получение исходной структуры из сетевого набора байт*)
pw^[j] := ROL(pw^[j],8);
END_FOR;
MV2AC; (*Исходные => конечные *)
В примере данные заносятся с адреса mv2ac.SRD, а то что SRD в расположена самой первой в структуре mva2c момент условно случайный. Сделай :
var
i : int;
SRD....
...
и все поймешь..
Понял:).
Вообще, спасибо большое за подробные объяснения. Понял, что как и почему.
ЗЫ
function get_original_from_net : bool
//Сетевые -> в исходные (для modbus.lib)
var_input
pdata : pointer to word;
size : byte; (*в байтах*)
end_var
------------
get_original_from_net := (pdata <> 0) and ((pdata mod 1) = 0); //не nil и четный
if get_original_from_net then
szdata := szdata / 2; //в регистрах-словах
...
end_if
Я так понимаю, что должно быть:
var_input
pdata : pointer to word;
size : byte; (*в байтах*)
end_var
var
szdata : byte; (*в байтах*)
end_var
------------
get_original_from_net := (pdata <> 0) and ((pdata mod 1) = 0); //не nil и четный
if get_original_from_net then
szdata := size / 2; //в регистрах-словах
...
end_if
ЗЗЫ. И ещё: Вы не рекомендуете
И я бы принципиально не стал делать в одном проходе из сетевого набора байт конечную структуру. При этом ваша функция это делает за раз. Или я что-то неправильно понимаю?
)) Да. Очепятался. Просто size на входе, size := size / 2, и далее везде size, дополнительно водить переменную здесь особо и не нужно
В смысле за раз ? И сетевого в исходный - да, за раз. Когда исходная=конечная этого достаточно (например считать все счетчики МДВВ). Но тут еще и исходная=>конечная нужно сделать, что дальше MV2/8A() и делает.
И, кстати, делать раздельные структуры единичного ai для 2AC и 8AC - не нужно. Описание статуса одинаково для 2A,8A,2AC,8AC,MVA8,PLC63/73/150/154/160 (конечно, афтару INCORRECT для 160-ого развальцевать кое-чего не помешало бы). Да и структура входа 2/8AC легко приводится (в целях унификации) к виду соответствующему 2/8A/MVA8. Или наоборот.
Огромное спасибо)))
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot