Не удается записать переменную типа real (float)

Стартовая страница Форумы Взаимодействие с устройствами Modbus Не удается записать переменную типа real (float)

Просмотр 15 сообщений - с 16 по 30 (из 45 всего)
  • Автор
    Сообщения
  • #4989
    manjey73
    Участник

    Посмотрите внимательнее мой код, там потом 4-х байтный массив увеличиваю до 8 байт (Double) и только после этого отправляю в ПЛК.

    Если вы будете крутить и там и сям то вы запутаетесь.

    #4995
    Mikhail
    Модератор

    Сейчас при отправке значения по Модбас драйвер делает следующее:
    Полученное значение команды типа double превращает в целое 2-байтное число без знака путем обрезания дробной части (ushort)cmd.CmdVal
    В список доработок этот вопрос включен.

    #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 байт):
    меняем на 4 элемента в коммуникаторе
    Затем переотправляю команду:
    повторная отправка команды
    Получаю:
    получившийся массив
    Запрягаю «ModBUS pull»:
    Настройка modbus pull
    Получаю:
    Результат modbus pull
    Перезапрягаю Modbus pull по другому:
    результат

    (Как меня достал местный метод вставки картинок…)
    Получаю тоже самое (0) только со знаком минус (-0)

    Как бы не срослось.

    • Ответ изменён 9 лет, 2 месяца назад пользователем VitaliyAT.
    • Ответ изменён 9 лет, 2 месяца назад пользователем VitaliyAT.
    #5001
    manjey73
    Участник

    Вы не поняли, я просто Серверу скармливаю double, поменяв во float байты так, чтобы это понял ПЛК, он его отправляет через Коммуникатор.

    В Самом ПЛК я просто принимаю переменную и он ее сразу воспринимает так, как должно.
    Такая перестановка рассчитана под конкретный ПЛК. в самом ПЛК я уже не делаю никаких перестановок.

    В настройках Коммуникатора ставлю «Множественная команда», количество элементов ДВА.
    То есть он отрежет от double сам лишние байты и отправит 4 байта в ПЛК.
    Если нужно отправить INT то есть всего 2 байта, то я даже формулу не вызываю, просто пишу число и ПЛК его правильно принимает.

    Через Команды Коммуникатора бесполезно отправлять, так как отправится «правильный» double для числа без переставления байт и как следствии нули в ПЛК…

    Байты на ПК вращаются согласно архитектуре процессора в littleEndian, а вот процы в ПЛК могут быть и с другой архитектурой а так же по разному хранить байты в переменных независимо от архитектуры.

    з.ы. не хватает такой же настройки с перестановкой байт как и при чтении с указанием типа переменной, чтобы можно было обходиться без формул. Тут согласен полностью, хотя это не смертельно

    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    #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.
    #5008
    manjey73
    Участник

    Непонятно только зачем в ПЛК все это делать. Мое мнение, не трогать передергивание байт в самом ПЛК, пусть работает как работает в зависимости от своей архитектуры и способа хранения байт в регистрах…

    #5009
    VitaliyAT
    Участник

    Может понадобиться любой вариант. Так как я спец в ПЛК и пока не шибкоспец в СКАДЕ, то мне её по меньше и надо задействовать, а в ПЛК я всё равно настройку ModBUS организую. Плюс сегодня одна СКАДА к нему цепляется, завтра властным решением рук-ва другая. Одна может вращать, другая нет.

    • Ответ изменён 9 лет, 2 месяца назад пользователем VitaliyAT.
    #5011
    manjey73
    Участник

    Это да, бывают экземпляры, где фиг повращаешь, я такие при изучении сразу в топку…

    #5013
    Mikhail
    Модератор

    Здесь добавил формулу для перестановки байт при отправки команды. Её можно подкорректировать в зависимости от количества устанавливаемых регистров. Также подходит для отправки «множественной» команды Модбас.

    #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.
    #5072
    VitaliyAT
    Участник

    Сдаётся мне сама формула не передаёт число в real, а просто меняет байты местами.

    #5073
    manjey73
    Участник

    а нафига вы в формуле пишите double SwapCmd() ?????

    double — это тип возвращаемой переменной. Имя функции SwapCmd() вот только это и надо писать…

    И еще раз, в Коммуникатор Сервером отправляется всегда double, а уже исходя из настроек Коммуникатора отправляется 2, 4 байта в прибор.

    CalcEngine.cs — это не лог, это как раз исходный код для исполнения Сервером всех формул. Сервер компилирует исходник и если видит синтаксические или иные ошибки сообщает об этом. А так же в документации указано, что если хоть в одном месте формул есть ошибка, Сервер работать не будет.

    И да, данная формула не для float а пример для usort всего лишь.

    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    • Ответ изменён 9 лет, 2 месяца назад пользователем manjey73.
    #5076
    manjey73
    Участник

    Формула работает, ошибок не вызывает, но у меня передает нули в прибор. Скорее всего не те байты или не в тех местах надо менять…

    Но по крайней мере не вызывает ошибок Сервера

    #5077
    VitaliyAT
    Участник

    исходя из настроек Коммуникатора отправляется 2, 4 байта в прибор

    Нет там таких настроек к сожалению… Получается нам хоть с формулами, хоть без всё равно кормить ПЛК даблами?

    С даблами своя проблема при чтении СКАДА-коммуникатором:
    Ввожу в СКАДЕ (В таблице значение 12.34) В ПЛК она приходит и расшифровывается нормально. А в СКАДА-комуникаторе читает 0, при настройке читать как double, и миллионы-миллардов, если попросить прочитать как real (то есть чтение как действие есть).

    • Ответ изменён 9 лет, 2 месяца назад пользователем VitaliyAT.
    #5080
    Mikhail
    Модератор

    Будет понятнее если Вы сформулируете так:
    1. Требуется отправить значение …
    2. В прибор необходимо записать байты … с помощью функции Мобас …
    3. На данный момент выполнены следующие настройки …
    4. В прибор отправляется …
    5. Проблема заключается в следующем: …

Просмотр 15 сообщений - с 16 по 30 (из 45 всего)
  • Для ответа в этой теме необходимо авторизоваться.