Стартовая страница › Форумы › Взаимодействие с устройствами › Управление контроллером DSE7320 по modbus
Помечено: Deepsea DSE7320 Modbus
- В этой теме 23 ответа, 4 участника, последнее обновление 2 месяца назад сделано
Mikhail.
-
АвторЗаписи
-
04.05.2023 в 12:46 #28394
George
УчастникДобрый день.
Имеется контроллер дизель-генератра DeepSea DSE7320.
С чтением данных вроде разобрался, но столкнулся с проблемой отправки команд на него. Сложность заключается в том, что контроллер реагирует на управление по модбас только при одновременной записи ключей в два регистра, причем во второй регистр ключ должен быть записан в обратном порядке бит.

Я пошел следующим путём:
1. В шаблоне КП добавил две команды : для регистров 4104 и 4105 с номерами команд кп 1 и 2 соттветственно.

также во втором отдельном случае пробовал менять код команды 6 на 16 (множественная команда)

2. Создал канал управления для триггера в ModAutoControl команда стоп- канал №8
3. В автоматическом управлении создал триггер: при канал8 = 1 идёт отправка двух команд ТУ с записью значений в указанные в шаблоне кп регистры:


В результате если в шаблоне кп была использована функия 6 для записи в регистр -комуникатор выдавал ошибку связи

А если в шаблоне кп стояла галочка «множественная команда» (функция 16), то комуникатор возвращал exception 2 illegal data adress. К сожалению скриншот не сохранил.
В обоих случаях контроллер на команды не реагировал.
Подскажите, пожалуйста, куда копать?04.05.2023 в 13:13 #28396
manjey73Участникpublic byte[] WriteSysDt() { DateTime dt = DateTime.Now; var year = BitConverter.GetBytes((ushort)dt.Year); byte[] cmdData = new byte[12] {0, (byte)dt.Minute, 0, (byte)dt.Second, 0, (byte)dt.Hour, 0, (byte)dt.Day, 0, (byte)dt.Month, 0, 0}; cmdData[10] = year[1]; cmdData[11] = year[0]; return cmdData; }Пример формулы записи времени через несколько регистров. Где секунды, минуты и так далее в виде целочисленных регистров.
04.05.2023 в 13:15 #28397
manjey73УчастникТо есть копайте в отправке модулем формулы, которая будет возвращать byte[]
а в настройках команды уже сами думайте, будет это набор регистров или это будет одна команда на требуемое количество регистров.04.05.2023 в 13:18 #28398
manjey73УчастникИзвиняюсь, команда должна быть одна, множественная с требуемы количеством регистров.
04.05.2023 в 14:03 #28401
MikhailМодераторДобрый день!
Посмотрите здесь в подпапке «Автор неизвестен», может быть что-то полезное найдёте. В KpModbus_DSE86oke.xml, похоже, аналогичная команда используется.Если 2 регистра имеют адреса подряд и должны быть записаны одной командой, то Модуль автоуправления не нужен. Если адреса не подряд и/или требуется 2 команды, то модуль нужен. В Вашей инструкции написано, что отправляется одной командой.
05.05.2023 в 11:06 #28407George
УчастникДействительно, судя по шаблону
KpModbus_DSE86oke.xml
нужно отправлять множественной командой в два подряд идущих регистра.
Но мне не хватает знаний, как это организовать. Ранее использовал команды для изменения конкретных регистров (например чтобы запустить команду запуск в контроллер Datakom — мне нужно в регистре №8193 бит№4 поставить в 1. Для этого я просто использовал команду записи с функцией 6 write holding registers с командой ТУ с формулой 16.)
Как работать с множественной командой я пока не разобрался.
На сколько я понял, если бы мне нужно был отправить одинаковое значение (напр. 35700) в два подряд идущих регистра, то я просто отправлял командой ТУ формулу 35700 с множественной командой в шаблоне на адресса 4104-4105. Но как одной командой отправить разные значения в 2 идущих подряд регистра?
Напр 35700 в регистр 4104 и 29835 в регистр 4105?05.05.2023 в 11:48 #28408
manjey73УчастникПример формулы давал выше.
Учитывая, что у вас всего два регистра, то есть 4 байта, можно команду сделать в виде uint, int и использовать при возврате формулы не byte[] для CmdData а просто Cmd.
Но это играться… проще наверное использовать CmdData и соответственно ваш код авторизации привести к ushort
При чем в первом варианте в массив вставить как есть, во втором переставить байты местами ну или вообще развернуть полностью все вплоть до битов. Не знаю как у вас точно должно выглядеть.05.05.2023 в 12:08 #28409
manjey73УчастникСудя по вашим значениям у вас просто переставлены байты местами во втором варианте.
Вы можете использовать пример, который я выложил с ushort но только для количества 2.
В формуле вам надо будет сделать примерно следующееpublic byte[] PassDSE(ushort val1) // тут вы подаете свое 35700, можете сделать входную как double чтобы забирать из канала а уже тут внутри формулы преобразовать в ushort и дальше обрабатывать { var valShort = BitConverter.GetBytes(val1); // байтовый массив вашего числа byte[] cmdData = new byte[4] {valShort[0], valShort[1], valShort[1], valShort[0]}; return cmdData; }з.ы. не проверял, но что-то в этом роде..
-
Ответ изменён 3 года, 1 месяц назад пользователем
manjey73.
05.05.2023 в 13:44 #28412
MikhailМодераторДля начала я бы рекомендовал в формуле канала управления вернуть массив из 16 байт со значениями 1, 2,… Посмотреть в журнале линии связи, что фактически отправится и расшифровать пакет с помощью https://rapidscada.net/modbus Скриншоты можете сюда приложить.
05.05.2023 в 15:33 #28415George
УчастникУважаемые Mikhail и manjey73, огромное Вам спасибо за уделённое время и помощь. Разобрался как правильно использовать формулы на сколько смог. В итоге всё заработало.
Использовал следующую формулу:
public byte[] PassDSE(ushort val1)
{
var valShort = BitConverter.GetBytes(val1);
byte[] cmdData = new byte[16] {
valShort[0], valShort[1], valShort[1], valShort[0],
valShort[0], valShort[1], valShort[1], valShort[0],
valShort[0], valShort[1], valShort[1], valShort[0],
valShort[0], valShort[1], valShort[1], valShort[0]
};
return cmdData;
}При установке в канале управления формулы PassDSE(35700) в онлайн парсере обнаружил что запись в регистры идёт наоборот:
запрос: 0A 10 10 08 00 02 04 74 8B 8B 74 17 E0
Part of Data Package Description Value
0A Slave address 0x0A (10)
10 Function code 0x10 (16) — Write Multiple Registers
10 08 Starting address Physical: 0x1008 (4104)
Logical: 0x1009 (4105)
00 02 Quantity 0x0002 (2)
04 Byte count 0x04 (4)
74 8B 8B 74 Registers value 0x748B (29835), 0x8B74 (35700)
17 E0 CRC 0x17E0 (6112)Изменил PassDSE(35700) на PassDSE(29835) и всё заработало.
Ещё раз огромное спасибо Вам! Добра, мира и хороших выходных 😉
05.05.2023 в 16:40 #28419
manjey73УчастникОго, а почему у вас массив из 16-ти байт? вам надо несколько раз повторять пароль в регистрах ?
з.ы. можно было просто поменять valShort[0], valShort[1], valShort[1], valShort[0]на valShort[1], valShort[0], valShort[0], valShort[1] по идее 🙂
05.05.2023 в 16:44 #28420
manjey73УчастникОго, а почему у вас массив из 16-ти байт? вам надо несколько раз повторять пароль в регистрах ?
з.ы. можно было просто поменять valShort[0], valShort[1], valShort[1], valShort[0]на valShort[1], valShort[0], valShort[0], valShort[1] по идее 🙂
Ну и если сделать входную переменную PassDSE(double val2) то внутри формулы можно сделать
ushort val1 = (ushort)val2
и соответственно формулу вызывать как PassDSE(Val(XXX)) где ХХХ — номер канала в котором вы храните пароль07.05.2023 в 16:44 #28436
MikhailМодераторЧто касается моего сообщения, я написал 16 байт с запасом. Используются ли они все или только часть станет видно в журнале при отправке команды.
Порядок байт можно в настройках команды задать. Но там только от 0-го до 9-го. Надо бы добавить A…F.
-
Ответ изменён 3 года, 1 месяц назад пользователем
Mikhail.
08.05.2023 в 12:22 #28448George
УчастникЗдравствуйте,
действительно, поправил формулу:
public byte[] PassDSE(ushort val1)
{
ushort val2Short = (ushort)(ushort.MaxValue — val1);
byte[] val1Bytes = BitConverter.GetBytes(val1);
byte[] val2Bytes = BitConverter.GetBytes(val2Short);
byte[] cmdData = new byte[4] { val1Bytes[1], val1Bytes[0], val2Bytes[1], val2Bytes[0] };
return cmdData;
}
Теперь работают почти все нужные команды: val1=35700 — ok,
val1=35701 — ok,
val1= 35705 -ok,
val1= 35706 -ok,
val1= 35734 — ok,но при val1= 35702 в логе коммуникоатора происходит следующее:
2023-05-08 12:17:44 Команда КП 1 «d500», тип: KpModbus, адрес: 10
Команда «Key»
Отправка (13): 0A 10 10 08 00 02 04 00 00 00 02 9B 2C
Приём (5/5): 0A 90 02 BC 03
Ошибка устройства: [02] ILLEGAL DATA ADDRESS!В modbus parser расшифровка:
Part of Data Package Description Value
0A Slave address 0x0A (10)
10 Function code 0x10 (16) — Write Multiple Registers
10 08 Starting address Physical: 0x1008 (4104)
Logical: 0x1009 (4105)
00 02 Quantity 0x0002 (2)
04 Byte count 0x04 (4)
00 00 00 02 Registers value 0x0000 (0), 0x0002 (2)
9B 2C CRC 0x9B2C (39724)Почему-то записывает 0,2 вместо 35702, 29833.
Вот пример правильной сработки при val1=35701:
Коммуникоатор:
Команда «Key»
Отправка (13): 0A 10 10 08 00 02 04 8B 75 74 8A 86 74
Приём (5/5): 0A 10 10 08 00
Приём (3/3): 02 C5 B1
OK!Online parser:
Part of Data Package Description Value
0A Slave address 0x0A (10)
10 Function code 0x10 (16) — Write Multiple Registers
10 08 Starting address Physical: 0x1008 (4104)
Logical: 0x1009 (4105)
00 02 Quantity 0x0002 (2)
04 Byte count 0x04 (4)
8B 75 74 8A Registers value 0x8B75 (35701), 0x748A (29834)
86 74 CRC 0x8674 (34420)-
Ответ изменён 3 года, 1 месяц назад пользователем
George.
08.05.2023 в 14:33 #28453
manjey73УчастникА не проще было обойтись без ushort.MaxValue? просто кинув по разному байты в массив?
-
Ответ изменён 3 года, 1 месяц назад пользователем
-
АвторЗаписи
- Для ответа в этой теме необходимо авторизоваться.