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

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

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

    Странно, очень странно… Холдинг регистр пишет одним порядком, а читает другим. При этом 10325476 — раскодирует не верно. Какая последовательность байт должна быть при чтении (и вообще зависит ли от неё что-либо, потому как это уже просто перебор, а не логический подбор — логически это 10325476)? Вот тут:

    #5084
    VitaliyAT
    Участник

    Тут уже 2 темы параллельно пошло, одна как оно работает без формулы и потом как работает формула:
    Начнём с того как оно работает без формулы:
    1. Требуется отправить значение …
    123,456
    2. В прибор необходимо записать байты … с помощью функции Модбас …
    Просто — да. )) ибо какие байты, кроме как соответствующие — не знаю. И да — по МодБАС.
    3. На данный момент выполнены следующие настройки …
    Создан канал для чтения холдинг регистра, при этом на скрине показан сразу порядок байт, но и без него результат примерно такой же:

    Создан канал для записи холдинг регистра

    настроенны таблицы и переданы в веб-морду:

    отправляю с неё значение (на тёмном воне можно наблюдать мильёнымильярдов — это если не трогать порядок чтения байт):

    ПЛК получает значение и верно расшифровывает его в пордке байт 10325476

    А коммуникатор видит 0:

    4. В прибор отправляется …
    123,456
    5. Проблема заключается в следующем: …
    СКАДА-коммуникатор неверно читает Дабл переменные записанные самой СКАДОЙ.

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

    Есть там настройки, запись одного регистра = 2 байта.
    Запись множественного количества 2 байта * количество регистров. Поставите 2, отправится 4 байта.

    Формула с перестановкой от Михаила похоже вообще не фурычит, я продвинул два байта по всему массиву, передача всегда 0

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

    manjey73, мы про это говорим?:

    Если да то при 4х приходит:

    А при 2х (как на скрине выше):

    Можно констатировать что если речь об этом, то просто снижение с 4 до 2х байт даёт ошибку, так как просто приходит 2 байта, а не перевод Double в Float и последующая его отправка. Может как-то с помощью формул можно в начале перегнать Double в Float , затем запихнуть его в 2 первых байта и отправить? Решит ли это вопрос чтения СКАДА-коммуникатором или породит ещё кучку вопросов?

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

    Как я отправляю float в Овен я писал выше, проверено на ПЛК63 и ПР200.
    А фот формула Михаила у меня не взлетает почему-то.

    Да, про это, при чем если выбрать запись одного регистра (команда 0х06) то вообще ничего переставлять не надо, Стандартная команда отправляет все корректно.

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

    Что-то не лады какие-то.
    Например если записать не (ushort)Cmd а

    Convert.ToUint16(Cmd) то получим ошибку компилирования формул.

    Ошибка при компилировании исходного кода формул:
    Строка 658, колонка 22: error CS0117: «System.Convert» не содержит определение для «ToUint16»

    Такая же ошибка, если сделать переменную uint и сделать конверт ToUint32
    Но если сделать переменную float и написать Convert.ToSingle(Cmd) то ошибки нет, все компилируется.

    Это как так ?

    #5096
    VitaliyAT
    Участник

    Для себя нашёл промежуточное [РЕШЕНИЕ] по приёму-передачи float (он же REAL = 32bit). Для меня это даже лучше, так как и планировалось работать Float переменными (требование заказчика ибо).
    НО! На будущее: Вопрос передачи-приёма Double (он же LREAL в ПЛК BnR = 64bit) остаётся не решённым.
    1) Заносим формулу от manjey73 в формулы (немного её изменив по части порядка присвоения). Главное нам из неё получить упаковку Double в Float:

    public double fRevers (int rev)
    {
    float q = Convert.ToSingle(CmdVal);
    byte[] f = new byte[4];
    byte[] o = new byte[4];
    f = BitConverter.GetBytes(q);
    Array.Copy(f,0,o,0,4);
    if (rev == 1234)
    {
    Array.Copy(f, 0, o, 0, 1);
    Array.Copy(f, 1, o, 1, 1);
    Array.Copy(f, 2, o, 2, 1);
    Array.Copy(f, 3, o, 3, 1);
    }
    Array.Resize(ref o, 8);
    Double ou = BitConverter.ToDouble(o,0);
    return ou;
    }

    2) Затем её вызываем в канале УПРАВЛЕНИЯ (а не входном), вот так:

    3) В СКАДА-коммуникаторе настраиваем канал управления так. Главное чтоб «кол-во элементов быоло 2»:

    4) А входящий канал так. Главное что float и порядок 3210 (его если менять, то в паре с формулой из п.1):

    5) Далее, дополнительные действия: в ПЛК организовать расшифровку пары байт как Float. На ST в среде B+R Automation Studio это выглядит так:

    FUNCTION MBT2Real
    
    	brsmemcpy((pReal+0), (pMBT+1), 1);
    	brsmemcpy((pReal+1), (pMBT+2), 1);
    	brsmemcpy((pReal+2), (pMBT+3), 1);
    	brsmemcpy((pReal+3), (pMBT+4), 1);
    
    	MBT2Real := 0;
    	RETURN;
    END_FUNCTION

    Где: pReal — это адрес элемента массива Real (Float) чисел, с которым потом работать логике ПЛК; pMBT — массив МодБАСа куда СКАДА скидывает значение (соответственно это Holding Registers).

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

    Ну формулу перестановки я и применял для каналов управления а не входных.

    Мне непонятно, почему формула Михаила вроде как работает в VS и не работает нифига в SCADA ??

    #5100
    VitaliyAT
    Участник

    зато я её пихал во входные — для себя пометку оставил ))) Вот про формулу Михаила ничего не скажу пока. Это вообще какой язык? С?

    #5101
    manjey73
    Участник

    C#, на котором сама SCADA и писана.

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

    Convert.ToUint16(Cmd) то получим ошибку компилирования формул.

    Ошибка при компилировании исходного кода формул:
    Строка 658, колонка 22: error CS0117: «System.Convert» не содержит определение для «ToUint16»

    Проверяйте регистр символов.

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

    2. В прибор необходимо записать байты … с помощью функции Модбас …
    Просто — да. )) ибо какие байты, кроме как соответствующие — не знаю. И да — по МодБАС.

    Имелось ввиду, сколько регистров (сколько байт) надо записать в прибор? Записать в каком формате, с плавающей точкой или как целое число?
    Какой номер функции Модбас для записи согласно документации на прибор?

    4. В прибор отправляется …
    123,456

    Скопируйте отправляемые данные из журнала работы линии связи.

    5. Проблема заключается в следующем: …
    СКАДА-коммуникатор неверно читает Дабл переменные записанные самой СКАДОЙ.

    Нужно скопировать принимаемые данные из журнала работы линии связи и указать, какое корректное значение Вы ожидаете.
    Уточните, проблема с отправкой команды или со считыванием значения тега?

    P.S. Обычно решение подобных проблем требует нескольких часов времени при удалённом подключении к клиенту. Время решения проблемы — основное отличие платной поддержки от бесплатной.

    #5107
    manjey73
    Участник

    Блин, действительно, правильно UInt (I тоже заглавная)…

    В любом случае предложенная вами формула для ushort почему-то не работает.
    я bit[0] и bit[1] по всему массиву подвигал, все равно запись идет нуля…
    без формулы у меня пишется 5100 (51 градус) и уже в ПЛК переводится как мне надо, отображаю как D.DD с двумя знаками после запятой.
    Если просто писать 51, то получу 0,51.

    Если использовать формулу, то всегда почему-то 0 как бы я не двигал байты.

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

    Формулы на форуме я не тестирую, но довольно странно, что передаются нули при любой перестановке. А Вы не пробовали явно прописать в неё значения байт?
    return BitConverter.ToDouble(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, 0);

    #5109
    manjey73
    Участник

    Заработала, возможно что-то не перезагрузил.
    Выйду из отпуска, проверю на флоатах.

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