Стартовая страница › Форумы › Взаимодействие с устройствами › Modbus › Не удается записать переменную типа real (float)
- В этой теме 44 ответа, 3 участника, последнее обновление 9 лет, 2 месяца назад сделано
manjey73.
-
АвторСообщения
-
30.03.2017 в 17:59 #4989
manjey73УчастникПосмотрите внимательнее мой код, там потом 4-х байтный массив увеличиваю до 8 байт (Double) и только после этого отправляю в ПЛК.
Если вы будете крутить и там и сям то вы запутаетесь.
31.03.2017 в 11:12 #4995
MikhailМодераторСейчас при отправке значения по Модбас драйвер делает следующее:
Полученное значение команды типа double превращает в целое 2-байтное число без знака путем обрезания дробной части (ushort)cmd.CmdVal
В список доработок этот вопрос включен.31.03.2017 в 11:26 #4998
VitaliyATУчастникА можно разжевать? Моя попытка:
public double fRevers (int rev) { float q = Convert.ToSingle(CmdVal); //конвертируем значение команды в float ("число с плавающей запятой одиночной точности") (как при этом вращаются байты ?№1) byte[] f = new byte[4]; //создаём новый массив для разворотов - "массив откуда" byte[] o = new byte[4]; //создаём новый массив для разворотов - "массив куда" f = BitConverter.GetBytes(q); //потрошим float в массив побайтно Array.Copy(f,0,o,0,4); //копируем ("массив откуда", координата элемента массива откуда, "массив куда", координата массива куда, сколько байт) - в данном случаи весь массив в весь массив if (rev == 1) //если реверс - да, то { Array.Copy(f, 0, o, 1, 1); // 1 в 2 Array.Copy(f, 1, o, 0, 1); // 2 в 1 Array.Copy(f, 2, o, 3, 1); // 3 в 4 Array.Copy(f, 3, o, 2, 1); // 4 в 3... таким образом 1234 = 2143 } Array.Resize(ref o, 8); //ресайзим массив до 8 элементов (то есть у нас получается 21340000 - где 0 пустой байт) Double ou = BitConverter.ToDouble(o,0); //запихиваем массив в дабл-число (как при этом вращаются байты ?№2) return ou; //возвращаем двойное число }Ок, допустим, что коммуникатор также выносит мозг ПЛК (как бы в этот момент осознав, что возврат такой изврат я бьюсь в тихой истерике).
Как мне готовить ПЛК к такому развитию событий? Предполагаю что считывать массив по 4 элемента в дабл, потом конвертить его куда и во что надо…
И я так понимаю «гудбай!» те проекты кто уже сделал МодБАС под 4 байта возврата с максимумом одним простым реверсом, (при том что его вообще можно не делать — простое человеческое «нахрена?» и «почему делая потенциально всеподходящий инструмент, так сузить его возможности в одном месте, что равносильно ставить под сомнение просто его применение!?») и хотели перевести свой АРМ на RapidSCADA.
Тем не менее беру меняю команду отправки в Коммуникаторе, чтоб отправлялось 4 элемента (каждый по 2 байта, того 8 байт):

Затем переотправляю команду:

Получаю:

Запрягаю «ModBUS pull»:

Получаю:

Перезапрягаю Modbus pull по другому:

(Как меня достал местный метод вставки картинок…)
Получаю тоже самое (0) только со знаком минус (-0)Как бы не срослось.
31.03.2017 в 12:13 #5001
manjey73УчастникВы не поняли, я просто Серверу скармливаю double, поменяв во float байты так, чтобы это понял ПЛК, он его отправляет через Коммуникатор.
В Самом ПЛК я просто принимаю переменную и он ее сразу воспринимает так, как должно.
Такая перестановка рассчитана под конкретный ПЛК. в самом ПЛК я уже не делаю никаких перестановок.В настройках Коммуникатора ставлю «Множественная команда», количество элементов ДВА.
То есть он отрежет от double сам лишние байты и отправит 4 байта в ПЛК.
Если нужно отправить INT то есть всего 2 байта, то я даже формулу не вызываю, просто пишу число и ПЛК его правильно принимает.Через Команды Коммуникатора бесполезно отправлять, так как отправится «правильный» double для числа без переставления байт и как следствии нули в ПЛК…
Байты на ПК вращаются согласно архитектуре процессора в littleEndian, а вот процы в ПЛК могут быть и с другой архитектурой а так же по разному хранить байты в переменных независимо от архитектуры.
з.ы. не хватает такой же настройки с перестановкой байт как и при чтении с указанием типа переменной, чтобы можно было обходиться без формул. Тут согласен полностью, хотя это не смертельно
31.03.2017 в 12:36 #5006
VitaliyATУчастникВскрыл я эту консервную банку. Помогла мне этом программа Floating Point Conversion и калькулятор Винды 10. (Перtвёл 10тизначные в HEX, )
Коммуникатор отправляет Double в последовательности байт 21436587:

Оставлю (главным образом для себя, остальные — велкам) рабочий код на ST:
(* MBT to Double *) FUNCTION MBT2Double brsmemcpy((pDouble+0), (pMBT+Order1), 1); brsmemcpy((pDouble+1), (pMBT+Order2), 1); brsmemcpy((pDouble+2), (pMBT+Order3), 1); brsmemcpy((pDouble+3), (pMBT+Order4), 1); brsmemcpy((pDouble+4), (pMBT+Order5), 1); brsmemcpy((pDouble+5), (pMBT+Order6), 1); brsmemcpy((pDouble+6), (pMBT+Order7), 1); brsmemcpy((pDouble+7), (pMBT+Order8), 1); brsmemcpy((pDouble+0), (pMBT+2), 1); brsmemcpy((pDouble+1), (pMBT+1), 1); brsmemcpy((pDouble+2), (pMBT+4), 1); brsmemcpy((pDouble+3), (pMBT+3), 1); brsmemcpy((pDouble+4), (pMBT+6), 1); brsmemcpy((pDouble+5), (pMBT+5), 1); brsmemcpy((pDouble+6), (pMBT+8), 1); brsmemcpy((pDouble+7), (pMBT+7), 1); MBT2Double := 0; RETURN; END_FUNCTION-
Ответ изменён 9 лет, 2 месяца назад пользователем
VitaliyAT.
31.03.2017 в 13:39 #5008
manjey73УчастникНепонятно только зачем в ПЛК все это делать. Мое мнение, не трогать передергивание байт в самом ПЛК, пусть работает как работает в зависимости от своей архитектуры и способа хранения байт в регистрах…
31.03.2017 в 14:41 #5009
VitaliyATУчастникМожет понадобиться любой вариант. Так как я спец в ПЛК и пока не шибкоспец в СКАДЕ, то мне её по меньше и надо задействовать, а в ПЛК я всё равно настройку ModBUS организую. Плюс сегодня одна СКАДА к нему цепляется, завтра властным решением рук-ва другая. Одна может вращать, другая нет.
-
Ответ изменён 9 лет, 2 месяца назад пользователем
VitaliyAT.
31.03.2017 в 16:26 #5011
manjey73УчастникЭто да, бывают экземпляры, где фиг повращаешь, я такие при изучении сразу в топку…
01.04.2017 в 09:55 #5013
MikhailМодераторЗдесь добавил формулу для перестановки байт при отправки команды. Её можно подкорректировать в зависимости от количества устанавливаемых регистров. Также подходит для отправки «множественной» команды Модбас.
04.04.2017 в 08:38 #5070
VitaliyATУчастникДобавил вашу формулу:
double SwapCmd() { ushort val = (ushort)Cmd; byte[] buf = BitConverter.GetBytes(val); return BitConverter.ToDouble(new byte[] { buf[1], buf[0], 0, 0, 0, 0, 0, 0 }, 0); }в ячейку «Формула» и поставил галку «использовать формулу» и передал СКАДА серверу.

После этого Сервер пишет:2017-04-04 10:15:38 <DESKTOP-VTI42UO><СИСТЕМА><ACT> Формулы считаны из базы конфигурации 2017-04-04 10:15:38 <DESKTOP-VTI42UO><СИСТЕМА><ERR> Ошибка при компилировании исходного кода формул: Строка 458, колонка 65: error CS1525: Недопустимый терм "double" в выражении Строка 458, колонка 74: error CS1002: ожидалась ; Строка 458, колонка 74: error CS1525: Недопустимый терм ")" в выражении Для ознакомления с исходным кодом см. файл D:\RapidSCADA\ScadaServer\Log\CalcEngine.cs 2017-04-04 10:15:38 <DESKTOP-VTI42UO><СИСТЕМА><ERR> Нормальная работа программы невозможна.(К стати не удобно что прямо из окна где это сообщение пишется в программе СКАДА-сервера назывемое «Журнал», нельзя это скопировать, надо лезть в лог файл. Хотябы кнопку рядом приварить, чтоб открывать блокнотом этот файл. А вообще растягивать окно Скада серверу не помешалот бы — все сообщения в форме «Журнал» не помещаются)
Почему данное действие вдруг свалило сервер и от этого нет зашиты — думаю отдельный баг репорт…
Так вот после удаления формулы через СКАДФ-администратор из этой ячейки ситуацию не меняет. Открытие файла CalcEngine.cs тоже делу не помогает — потому что это тоже лог и удаление указанной строки (458) не помогает
Теперь у меня сервер лежит и как его поднять я не понимаю.
UPD: Засунул формулу в Формулы вот так:

Поменял место куда вношу формулу — в каланы управления перетащил:

Сообщение от Сервера сменилось на:
2017-04-04 10:50:22 <DESKTOP-VTI42UO><СИСТЕМА><ACT> Формулы считаны из базы конфигурации 2017-04-04 10:50:22 <DESKTOP-VTI42UO><СИСТЕМА><ERR> Ошибка при компилировании исходного кода формул: Строка 464, колонка 102: error CS1502: Наиболее подходящий перегруженный метод для "System.Convert.ToDouble(object)" имеет несколько недопустимых аргументов Строка 464, колонка 119: error CS1503: Аргумент "1": преобразование типа из "группа методов" в "object" невозможно Для ознакомления с исходным кодом см. файл D:\RapidSCADA\ScadaServer\Log\CalcEngine.cs 2017-04-04 10:50:22 <DESKTOP-VTI42UO><СИСТЕМА><ERR> Нормальная работа программы невозможна.-
Ответ изменён 9 лет, 2 месяца назад пользователем
VitaliyAT.
04.04.2017 в 09:11 #5072
VitaliyATУчастникСдаётся мне сама формула не передаёт число в real, а просто меняет байты местами.
04.04.2017 в 09:33 #5073
manjey73Участника нафига вы в формуле пишите double SwapCmd() ?????
double — это тип возвращаемой переменной. Имя функции SwapCmd() вот только это и надо писать…
И еще раз, в Коммуникатор Сервером отправляется всегда double, а уже исходя из настроек Коммуникатора отправляется 2, 4 байта в прибор.
CalcEngine.cs — это не лог, это как раз исходный код для исполнения Сервером всех формул. Сервер компилирует исходник и если видит синтаксические или иные ошибки сообщает об этом. А так же в документации указано, что если хоть в одном месте формул есть ошибка, Сервер работать не будет.
И да, данная формула не для float а пример для usort всего лишь.
04.04.2017 в 09:45 #5076
manjey73УчастникФормула работает, ошибок не вызывает, но у меня передает нули в прибор. Скорее всего не те байты или не в тех местах надо менять…
Но по крайней мере не вызывает ошибок Сервера
04.04.2017 в 10:28 #5077
VitaliyATУчастникисходя из настроек Коммуникатора отправляется 2, 4 байта в прибор
Нет там таких настроек к сожалению… Получается нам хоть с формулами, хоть без всё равно кормить ПЛК даблами?
С даблами своя проблема при чтении СКАДА-коммуникатором:
Ввожу в СКАДЕ (В таблице значение 12.34) В ПЛК она приходит и расшифровывается нормально. А в СКАДА-комуникаторе читает 0, при настройке читать как double, и миллионы-миллардов, если попросить прочитать как real (то есть чтение как действие есть).-
Ответ изменён 9 лет, 2 месяца назад пользователем
VitaliyAT.
04.04.2017 в 13:02 #5080
MikhailМодераторБудет понятнее если Вы сформулируете так:
1. Требуется отправить значение …
2. В прибор необходимо записать байты … с помощью функции Мобас …
3. На данный момент выполнены следующие настройки …
4. В прибор отправляется …
5. Проблема заключается в следующем: … -
Ответ изменён 9 лет, 2 месяца назад пользователем
-
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.