Опрос СТУ-1

Просмотр 14 сообщений - с 1 по 14 (из 14 всего)
  • Автор
    Сообщения
  • #32566
    Wizard256
    Участник

    Здравствуйте!
    Есть прибор СТУ-1 работает по Modbus. С текущими значениями разобрался по документации (для float порядок байт 2301). Проблема с Накопленными значениями Например накопленная энергия Е1 в документации написано:
    002E/002F/0030/0031 Накопленная тепловая энергия 1 тепловвода E1, ГДж тип long/float
    Значения накопленного объема (накопленной массы, накопленной энергии) представляют две составляющие типа long и float. В четырех первых байтах содержится целая часть значения (long), в остальных четырех – вещественная (float).
    Инструкция к СТУ-1 по модбас
    Лог Коммуникатора:
    Запрос значений группы элементов «Nakopl»
    Отправка (8): 01 03 00 2E 00 38 24 11
    Приём (2/2): 01 03
    Приём (115/115): 70 90 AF 00 06 8C 13 3F 0F F8 F7 00 02 79 E1 3E 66 00 00 00 00 00 00 00 00 00 00 00 00 9C 05 33 EF 65 C0 00 1B 9C 54 3D 14 48 5F 00 27 96 3D 3E BC 57 55 00 0C C7 7C 3F 36 F9 28 00 0B 53 72 3E 8F 00 00 00 00 00 00 00 00 00 00 00 00 D5 4A 33 EC CB 24 00 19 38 7C 3F 65 B5 18 00 25 C2 D1 3E 16 D2 B8 00 0B D4 18 3E 34 78 F4 00 0B BA 93 3F 2E 3B 28
    ОК
    вопрос, как мне получить значение E1 (на экране прибора E1=430255.560731)
    из этих 8 байт 90 AF 00 06 8C 13 3F 0F
    Онлайн конвертеры говорят:
    00 06 90 AF = 430255
    3F 0F 8C 13 = 0.5607311
    собственно как из 8 байт собрать число Е1 не плодя каналы
    пока настройки такие:
    <?xml version=»1.0″ encoding=»utf-8″?>
    <DeviceTemplate>
    <Options>
    <ZeroAddr>true</ZeroAddr>
    <DecAddr>false</DecAddr>
    <DefByteOrder2 />
    <DefByteOrder4 />
    <DefByteOrder8 />
    </Options>
    <ElemGroups>
    <ElemGroup active=»true» dataBlock=»HoldingRegisters» address=»0″ name=»Izmereniya»>
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v1″ name=»v1″ />
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v2″ name=»v2″ />
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v3″ name=»v3″ />
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v4″ name=»v4″ />
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v5″ name=»v5″ />
    <Elem type=»float» byteOrder=»2301″ readOnly=»true» isBitMask=»false» tagCode=»v6″ name=»v6″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t1″ name=»t1″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t2″ name=»t2″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t3″ name=»t3″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t4″ name=»t4″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t5″ name=»t5″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»t6″ name=»t6″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»p1″ name=»p1″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»p2″ name=»p2″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»p3″ name=»p3″ />
    <Elem type=»ushort» readOnly=»true» isBitMask=»false» tagCode=»p4″ name=»p4″ />
    </ElemGroup>
    <ElemGroup active=»true» dataBlock=»HoldingRegisters» address=»46″ name=»Nakoplennie dannie»>
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»e1″ name=»e1″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»e2″ name=»e2″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv1″ name=»nv1″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv2″ name=»nv2″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv3″ name=»nv3″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv4″ name=»nv4″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv5″ name=»nv5″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nv6″ name=»nv6″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm1″ name=»nm1″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm2″ name=»nm2″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm3″ name=»nm3″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm4″ name=»nm4″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm5″ name=»nm5″ />
    <Elem type=»long» readOnly=»true» isBitMask=»false» tagCode=»nm6″ name=»nm6″ />
    </ElemGroup>
    <ElemGroup active=»true» dataBlock=»HoldingRegisters» address=»102″ name=»Vremya narabotki»>
    <Elem type=»int» byteOrder=»012″ readOnly=»false» isBitMask=»false» tagCode=»tt1″ name=»tt1″ />
    <Elem type=»int» byteOrder=»012″ readOnly=»false» isBitMask=»false» tagCode=»tt2″ name=»tt2″ />

    Так же интересно интересно время наработки.
    Из документации:

    0066/0067 Время наработки 1 канала, мин тип 3 байта
    Накопленное время наработки хранится в младших 3 байтах, в минутах.

    Из коммуникатора:
    Запрос значений группы элементов «Twr»
    Отправка (8): 01 03 00 66 00 04 A4 16
    Приём (2/2): 01 03
    Приём (11/11): 08 A0 9B 2C 04 A3 EF 2C 0C 4C 7E
    OK
    на экране прибора значение 5054,32.
    С программированием не дружу, специфика работы КИПиА.
    Заранее спасибо.

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

    Добрый день!

    В четырех первых байтах содержится целая часть значения (long), в остальных четырех – вещественная (float).

    Считать целую и дробную часть числа как отдельные теги устройства. Они запишутся в разные каналы. Затем в расчётном канале сложить их для получения конечного результата. Неудобно, конечно, но как видите, значения имеют разные типы данных.

    0066/0067 Время наработки 1 канала, мин тип 3 байта
    Накопленное время наработки хранится в младших 3 байтах, в минутах.

    Забрать данные в канал и в формуле канала по маске взять 3 байта.

    > С программированием не дружу, специфика работы КИПиА
    Программирование не понадобится. Только формулы из математики.

    P.S. Разбирать настройки в XML на глаз вряд ли кто-то будет. Делайте скриншоты настроек.

    #32573
    Wizard256
    Участник

    Добрый день!
    С накопленными разобрался, на каждое значение сделал 2 канала 1 int и 2 float, потом доделаю каналы с суммами 2х чисел. Проблема с временем наработки.
    из лога коммуникатора:
    Запрос значений группы элементов «Vremya narabotki»
    Отправка (8): 01 03 00 66 00 04 A4 16
    Приём (2/2): 01 03
    Приём (11/11): 08 A0 9B 2C 04 A3 EF 2C 0C 4C 7E
    OK

    здесь 2 числа
    Twr1: A0 9B 2C 04
    Twr2: A3 EF 2C 0C
    далее на табло у нас значение в часах, например Twr2=13806.65 далее переводим в минуты получаем 828 399. Онлайн калькулятор нам говорит 00 0C A3 EF , т.е. если я правильно понял то порядок байт 301.
    На выходе получаем не то что надо, куда копать ?
    скрин и файлы
    Ссылка на диск

    • Ответ изменён 2 года, 1 месяц назад пользователем Wizard256. Причина: добавление ссылки
    • Ответ изменён 2 года, 1 месяц назад пользователем Wizard256.
    #32576
    JurasskPark
    Участник

    Twr1: A0 9B 2C 04
    В карте регистров написано 3байта.
    То есть A0 — выкидываете.
    9B 2C 04 — ‭10 169 348 минут

    #32577
    Wizard256
    Участник

    Я чего-то не понимаю, в приборе Twr1 = 5054.32 (округлено) т.е. 303259 минут. По калькуляторам онлайн нужно выкинуть 2С и собрать биты в 04 A0 9B — 303259
    как это сделать ?

    #32578
    JurasskPark
    Участник

    Есть такой понятие как старший байт, младший байт.
    Если представление числа в машинном коде (то есть, в двоичной форме) занимает больше 8 бит (1 байта) , то оно разбивается на несколько байт. Типичный случай — представление целых чисел (integer) в 32-разрядных операционках занимает 32 бита, то есть 4 байта.

    Первый байт — разряды 1-8,
    второй байт — разряды 9-16,
    третий байт — разряды 17-24,
    и так далее.

    Байт, в котором хранятся младшие разряды (1-8) — младший, в котором старшие — старший.

    303259 = 04 A0 9B, но так как регистр в модбасе по умолчанию 2 байта, то слева нужно добавить 0. Получиться 00 04 A0 9B
    То есть 00 04 A0 9B состоит из 2 регистров.
    00 04 — первый регистр
    A0 9B — второй регистр

    00 04 A0 9B
    00 — старший байт (первый регистр)
    04 — младший байт (первый регистр)
    A0 — старший байт (второй регистр)
    9B — младший байт (второй регистр)

    Теперь через формулу подставить полученный целое число и получить младший байт.
    Сейчас под рукой нет скады. Но вроде там было.

    ushort number = Convert.ToUInt16(«3510»);
    byte upper = (byte) (number >> 8);
    byte lower = (byte) (number & 0xff);

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

    Общая идея как выделить 3 байта из значения канала:
    1. Канал хранится как double. Поэтому прежде, чем брать 3 байта, значение канала нужно преобразовать в целый тип. Пожалуй, int подойдёт. На C# int — это 4 байтное целое со знаком.
    2. Если нужно удалить старший байт, то применить двоичное умножение на число 0x00FFFFFF
    Если нужно удалить младший байт, то сдвинуть вправо на 8 бит

    Формулы уже написаны выше, но удобнее экспериментировать сразу с формулой канала. Она будет примерно такая:
    ((int)Cnl) & 0x00FFFFFF
    или
    ((int)Cnl) >> 8
    (не проверял)

    #32582
    Wizard256
    Участник

    Спасибо за помощь! Методом перебора в настройках шаблона выставил порядок 230 и получил свои минуты просто считать нужно было с права на лево. посмотрим как будет дальше, а пока значения совпадают с тем что мне нужно. Далее просто Cnl/60 и всё должно быть почти как на экране прибора. Или лучше через формулу а порядок байт в настройках убрать?

    #32583
    Wizard256
    Участник

    Как я понял по Онлайн конвертерам и Яндексу, прибор выдаёт значения в Mid-Little Endian (CDAB) (Скорее всего касается и приборов УРЖ2КМ у них один производитель).
    В перспективе осталось разобраться с текущим временем прибора 1 регистр в 6 байт (Скорее всего дергать как uLong 1им каналом или 3мя в ushort), в каждом байте десятичное число даты и времени. Скорее всего придется раскладывать на каждый байт по отдельности, конвертировать в десятичное число и собирать в строку.

    #32599
    Wizard256
    Участник

    Извиняюсь если достал, насколько я понял драйвер сам по порядку байт собирает число
    и заполняет нулями.
    Теперь вопрос как собрать из 2х чисел в 4 байта и 2 байта Чтобы потом Можно было воспользоваться DecodeDate(val). Почитав интернет попробовал собрать 2 числа в 1
    в vscodec сделал так:

    UInt32 d = 0x1e041810 ;
    ushort t = 0x1224 ;
    double val = ((long)d << 16)|((Int16)t ) ;
    Console.WriteLine(«,»+val);
    ,33002932408868

    по байтам вроде как надо.
    Теперь вопрос как это реализовать в Скаде в расчетном канале?
    заранее спасибо.

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

    Если в скаде эти числа записаны в разных каналах, то простой вариант формулы расчётного канала будет
    ((long)Val(101) << 16)|((Int16)Val(102))
    где 101 и 102 — номера соответствующих каналов.
    Формула не учитывает статусы каналов, но для теста её будет достаточно.

    #32646
    Wizard256
    Участник

    Спасибо за помощь!
    В общем после долгих танцев с бубном и из-за недостатка знаний, сделал чтение 3х регистров short и создал 6 расчетных каналов. Далее с помощью операций показанных ранее по смещения и умножения получил отдельные цифры даты и времени. Как сделать лучше пока не придумал. Скриншоты на диске по ссылке. В текстовом файле есть строка преобразования данных в дату и время, только пока не понятно как ее прикрутить к Скаде чтобы уменьшить количество каналов. Если кто сможет помочь буду благодарен.

    #32647
    manjey73
    Участник

    @Wizard256 если часть операций можно сделать сразу во входном канале, то может получится сократить расчетные.

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

    Если много каналов используют аналогичные формулы, то формулу можно внести в таблицу Скрипты в виде отдельной функции, чтобы было удобнее её вызывать.
    Длинную формулу тоже лучше сделать отдельной функцией.

    public double MyFunc()
    {
      return ...
    }
    
Просмотр 14 сообщений - с 1 по 14 (из 14 всего)
  • Для ответа в этой теме необходимо авторизоваться.