Ответы в темах
-
АвторСообщения
-
7in
УчастникПриношу извинения за то, что пропал на некоторое время. Огромное Вам спасибо за проделанную работу. Изучу Ваш драйвер и протестирую на своих приборах. О результатах обязательно здесь отпишусь.
7in
УчастникКонтрольные суммы верные. В ручном режиме можно вот здесь считать/проверять:
https://onlinehextools.com/xor-hex-numbers
Доступ к прибору организую. Будет MOXA Nport в режиме TCP Server.
Чуть позже предоставлю IP адрес и порт для доступа к устройству.7in
Участникпо вашему же коду всего два байта… то есть 4 символа hex
Все верно. Первый символ hex — это команда (чтение, запись high/lowbyte), остальные три это адрес в памяти. В этом можно убедиться открыв мой скриншот из протокола обмена (прикладывал выше) там в таблице указаны адреса в памяти — они состоят из трех hex символов.
Может быть есть смысл сделать драйвер вроде того, как реализовано чтение модбас регистров? Т.е. при настройке мы будем указывать вручную первый и второй байт (для записи нужно продумать механизм отдельно). Задачей драйвера в таком случае будет посчитать контрольную сумму, отправить массив байт, считать ответ, проверить контрольную сумму. Привести считанное значение к нужному виду можно уже через формулы в самой RapidSCADA, можно это в драйвере не реализовывать.
В таком случае драйвер получится универсальным и будет подходить под любое приложение. Минус в том, что вручную придется заносить все параметры.
Таким образом еще и решится проблема считывания только необходимых параметров. Т.к. драйвер будет читать только то, что мы сами задали, лишних запросов к устройству не будет.7in
УчастникДа, все верно. Т.к. адрес в RAM состоит из трёх hex символов.
7in
УчастникЗабыл ответить насчет деления на 128: не знаю точно с чем эта необходимость связана (возможно разрядность АЦП), но в протоколе обмена на стр. 7 есть формула как получить значение температуры, и там нужно делить на 128.
Как правило все остальные параметры не нужно преобразовывать, только из hex в dec перевести и все. Тоесть это только с датчиками температуры такие заморочки с делением.
7in
УчастникВот например адреса RAM и EEPROM для значений уставки горячей воды
https://disk.yandex.ru/i/Y242o-PyH02SRw
Как можно видеть в EEPROM у них одинаковый адрес, отличается только low/high byte-
Ответ изменён 4 года, 1 месяц назад пользователем
7in.
7in
УчастникКод для всех преобразований предоставить не представляется возможным, т.к. как я уже говорил у контроллера есть различные «приложения», у каждого приложения свои параметры со своей адресацией в памяти. Частично это описано в конце протокола обмена, там есть таблицы с адресами хранения параметров в памяти.
Есть параметры, одинаковые для всех приложений (как например показания датчиков температуры), для них адрес в памяти соответственно всегда один будет.Писать одновременно два байта (старший и младший) практически никогда не придется, так как почти все параметры занимают один байт, соответственно и писать придется один байт. Просто некоторые параметры хранятся в верхнем байте, а некоторые в нижнем. При этом адрес в памяти у них одинаковый будет. Поэтому нужны разные команды.
Немного сумбурно объяснил, если что-то непонятно — напишите 🙂7in
УчастникВозьмем простой пример: регулятор используется чтобы поддерживать постоянную температуру горячей воды. Значение температуры задано на самом контроллере, допустим это 60 градусов. Это значение контроллер хранит у себя и в RAM и в EEPROM. Если мы хотим изменить удаленно температуру например на 65 градусов — нам нужно сначала записать новое значение в RAM, а затем в EEPROM. Думаю понятно что если не записать в EEPROM — то после перезагрузки значение сбросится на 60 градусов. Если записать наоборот только EEPROM — то тогда новое значение применится только после перезагрузки.
7in
УчастникНе совсем понял в чем вопрос. EEPROM можно только отдельно high и low byte записывать. RAM в принципе одной командой сразу два байта можно записать (Dx), либо так же отдельно верхний и нижний.
Запись нужна чтобы менять настройки контроллера. Писать нужно и RAM и EEPROM.
В целом запись значений сейчас не так важна, мне бы с чтением разобраться…7in
УчастникНе могу разобраться как посмотреть описание объекта «Connection». В других проектах в VS2022 можно было от вызова метода перейти к его описанию, но видимо когда я открываю DevTesterLogic.cs у меня в VS не подключены используемые классы и он не позволяет посмотреть их описание.
Приношу извинения, понимаю что вопрос скорее всего очень глупый, но все же: как посмотреть каким образом работает «Connection», что ему нужно передавать, в каком формате и т.д. ?7in
Участникдва байта ответа после проверки полученного ответа представляют из себя всегда один и тот же тип данных
К сожалению нет, типы данных разные. Приведенный код относится только к значениям температур. Остальные параметры хранятся в различных типах данных и требуют преобразования.
Для начала я думаю вполне подойдет ваш вариант: задаем true/false около параметров, которые хотим/не хотим запрашивать. Контрольную сумму запросов действительно можно посчитать заранее и затем просто отправлять заготовленный массив байт.
Пока не могу разобраться как скомпилировать свой проект из VS2022 в dll, чтобы он был доступен при выборе драйвера в приложении Администратор
7in
УчастникТак понимаю это конфигурируемые приборы и не всегда используются все входы/выходы, как те же датчики. И тогда нет смысла читать то, что не используется, учитывая, что на каждый параметр свой запрос.
Все верно. У приборов есть разные схемы применения, от них зависит набор доступных парамтеров для чтения и записи. Помимо этого согласно документации после получения ответа, перед отправкой новго запроса следует выждать 400мс. Таким образом чтение ненужных параметров будет очень сильно увеличивать время опроса.
7in
УчастникВот мой код, который запрашивает значение датчиков температуры:
static byte[] SendCheck(byte a, byte b)//Функция принимает на вход 2 байта. //Функция отправляет массив байт, через задержку читает ответ и проверяет КС. { NetworkStream stream = client.GetStream(); byte[] datasend = {a,b,0,0,0 };//массив байт для отправки int checksum = datasend[0] ^ datasend[1] ^ datasend[2] ^ datasend[3]; //Считаем контрольную сумму массива для отправки datasend[4] = Convert.ToByte(checksum); //Записываем расчитанную контрольную сумму в конец массива (5 байт) stream.Write(datasend, 0, 5);//Записываем в TCP поток byte[] dataread = new byte[5];//Массив для приема Thread.Sleep(1000);//Ждем ответа stream.Read(dataread, 0, 5);//Читаем массив 5 байт из TCP потока checksum = dataread[0] ^ dataread[1] ^ dataread[2] ^ dataread[3]; //Считаем контрольную сумму для принятых байт if (dataread[4] == Convert.ToByte(checksum) & dataread[1] == datasend[0]) //Если КС совпадает - функция возвращает результат, иначе нули { byte[] readresult = { dataread[2], dataread[3] }; return readresult; } else { byte[] readresult = { 0x00, 0x00 }; Console.WriteLine("Ошибка чтения"); return readresult; } } static string[] ReadSensors()//Чтение значений всех датчиков { string[] temperature = new string[10]; byte[] RAMadrSensors = { 0x3A, 0x38, 0x36, 0x34, 0x32, 0x30, 0x46, 0x48, 0x4A, 0x4C }; //Адреса в RAM:S1,2,3,4,5,6,CalcCirc1,CalcCirc2,CalcReturn1,CalcReturn2 byte i = 0; byte s = 1; foreach (byte b in RAMadrSensors) { byte[] result = SendCheck(0xCE, b); // Отправляем функцию чтения из RAM и адрес в памяти из массива RAMadrSensors byte[] resultreversed = { result[1], result[0] }; // Переворачиваем байты ответа наоборот short temp16bit = BitConverter.ToInt16(resultreversed, 0); // Получаем Int16 из массива двух байт float temp128 = (float)temp16bit / 128; // Превращаем значения в float temperature[i] = temp128.ToString("F1"); //Превращаем в строку Console.WriteLine("Sensor " + s + ": " + temperature[i] + "°C"); i++; s++; } return temperature; //Возвращаем массив температур }7in
УчастникСсылка на гитхаб почему то сломалась. Вот нормальная : github.com/codingandmore/ecl300
7in
УчастникЛогика достаточно простая. На данный момент мне было бы достаточно получать данные с датчиков температуры (6 штук). В будущем конечно планировал добавить запись значений, чтение конфигурации и т.д.
Поэтому думаю вариант жестко задать в драйвере параметры, не прибегая к шаблонам — это как раз мой вариант.
Единственное хотелось бы иметь возможность запрашивать только необходимые параметры (например только датчики № 1,3,4), нужны ли для этого шаблоны?Что касается примеров кода — свои исходники честно говоря мне стыдно показывать, т.к. там все ужасно написано, но есть <ahref=»https://github.com/codingandmore/ecl300″>библиотека на GitHub, написанная другим человеком. Написана на Java, но думаю сама логика запросов там будет понятна.
Если кратко как происходит обмен: Посылаем 5 байт, в ответ контроллер отвечает тоже 5 байт.
Структура запроса:
Первый и второй байт — функция запроса и адрес в памяти устройства
Третий и четвертый — записываемые значения (если просто читаем — равны 0)
Пятый байт — контрольная сумма
Структура ответа:
Первый и второй байт — запрошенная функция, либо код ошибки
Третий и четвертый — результат чтения
Пятый — контрольная суммаСоответственно все значения считываются по одному, никакого объединения как в Modbus нет. Сетевого адреса у устройства тоже нет.
-
Ответ изменён 4 года, 1 месяц назад пользователем
-
АвторСообщения