Дата время (BCD)

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

    Здравствуйте!
    Ситуация следующая: прибор имеет ряд значений времени, описаны производителем как:
    Register Size Mode/Access Data Type Description полученное
    (Reg) значение
    0 1 Только чтение uint16 текущая дата, ДДММ(BCD) 5636
    1 1 Только чтение uint16 текущая дата, ГГ(BCD) 8226
    2 1 Только чтение uint16 текущее время, ЧЧММ(BCD) 5926
    9 1 Только чтение uint16 дата конфигурации, ДДММ(BCD) 5380
    10 1 Только чтение uint16 дата конфигурации, ГГ(BCD) 8226
    11 1 Только чтение uint16 время конфигурации, ЧЧММ(BCD) 5144
    22 2 Только чтение uint32 Наработка 6480
    23

    Как я понимаю BCD — это двоично-десятичный код

    В программе производителя это описано так:
    private float GetFloatFrom2SHORT(ushort high, ushort low)
    {
    var hbytes = BitConverter.GetBytes(high);
    var lbytes = BitConverter.GetBytes(low);
    byte[] blist = new byte[4];
    blist[0] = hbytes[0];
    blist[1] = hbytes[1];
    blist[2] = lbytes[0];
    blist[3] = lbytes[1];
    return BitConverter.ToSingle(blist, 0);
    }

    private uint GetUint32From2SHORT(ushort high, ushort low)
    {
    var hbytes = BitConverter.GetBytes(high);
    var lbytes = BitConverter.GetBytes(low);
    byte[] blist = new byte[4];
    blist[0] = hbytes[0];
    blist[1] = hbytes[1];
    blist[2] = lbytes[0];
    blist[3] = lbytes[1];
    return BitConverter.ToUInt32(blist, 0);
    }

    public void GetCommon()
    {
    ushort[] receive;
    try
    {
    receive = mdbs.ReadHoldingRegisters(1, indxMDBS_COMMON, LEN_MDBS_COMMON);
    }
    catch { isConnected = false; return; }

    ushort DD, MM, hh, mm, YY;

    int op_indx = indxMDBS_COMMON;

    DD = (ushort)((receive[op_indx + indx_MDBS_COMMON_CURR_DDMM] >> 8) & 0x00FF);
    MM = (ushort)((receive[op_indx + indx_MDBS_COMMON_CURR_DDMM] >> 0) & 0x00FF);
    YY = receive[op_indx + indx_MDBS_COMMON_СURR_YY];
    hh = (ushort)((receive[op_indx + indx_MDBS_COMMON_CURR_hhmm] >> 8) & 0x00FF);
    mm = (ushort)((receive[op_indx + indx_MDBS_COMMON_CURR_hhmm] >> 0) & 0x00FF);

    dateTime = $»{hh.ToString(«X2»)}:{mm.ToString(«X2»)} {DD.ToString(«X2»)}.{MM.ToString(«X2»)}.{YY.ToString(«X4″)}»;
    DD = (ushort)((receive[op_indx + indx_MDBS_COMMON_CONF_DDMM] >> 8) & 0x00FF);
    MM = (ushort)((receive[op_indx + indx_MDBS_COMMON_CONF_DDMM] >> 0) & 0x00FF);
    YY = receive[op_indx + indx_MDBS_COMMON_CONF_YY];
    hh = (ushort)((receive[op_indx + indx_MDBS_COMMON_CONF_hhmm] >> 8) & 0x00FF);
    mm = (ushort)((receive[op_indx + indx_MDBS_COMMON_CONF_hhmm] >> 0) & 0x00FF);

    dateTimeConf = $»{hh.ToString(«X2»)}:{mm.ToString(«X2»)} {DD.ToString(«X2»)}.{MM.ToString(«X2»)}.{YY.ToString(«X4″)}»;
    }

    (на чем написано не знаю, про наработку тоже не нашёл код)

    Помогите, пожалуйста, с формулой для придания данным даты и времени человеческого вида?

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

    Добрый день!

    Синтаксис C#. Только в формулах Rapid SCADA не поддерживается ключевое слово var. Нужно явно писать тип.

    Т.к. формулы довольно сложные, я бы рекомендовал установить Visual Studio 2022 Community, создать простейшее консольное приложение и сначала отладить эти формулы. Затем вставить в таблицу формул.

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

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

    0 1 Только чтение uint16 текущая дата, ДДММ(BCD) 5636

    Что означает эта фраза на человеческом языке?
    Вот Вы допустим считали значение регистра 16-бит. Как из него получить день и месяц?

    #23077
    manjey73
    Участник

    С трудом себе представляю 56 день и 36 месяц или наоборот.
    А так же 8226 год…

    #23079
    VylegzhaninD
    Участник

    5636 — это значение в два байта, так? А по BCD я так понимаю надо каждый байт разбирать отдельно и отдельно переводить в десятичную систему…

    #23080
    VylegzhaninD
    Участник

    Из википедии:
    Двоично-десятичный код (англ. binary-coded decimal), BCD, 8421-BCD — форма записи рациональных чисел, когда каждый десятичный разряд числа записывается в виде его четырёхбитного двоичного кода. Таким образом, каждая тетрада двоично-десятичного числа может принимать значения от 00002 (010) до 10012 (910).

    Например, десятичное число 31110 будет записано в двоичной системе счисления в двоичном коде как 1 0011 0111, а в двоично-десятичном коде как 0011 0001 0001.

    #23081
    manjey73
    Участник

    BCD формат, это когда в тетраде может быть число от 0 до 9 и никаких A-F

    То есть число 99 и в байте будет выглядеть как 99h

    А у вас производитель что-то напридумывал свое, но при этом ни в одном примере в числах нет букв A-F

    Очень странно все это…

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

    ДДММ(BCD) 5636

    Рассмотрим 5636.
    В двоичном коде это 0001 0110 0000 0100
    То есть 16.04

    Формулы для таблицы формул будут примерно такие:

    public double GetDay(double val)
    {
      ushort x = (ushort)val;
      int d1 = (x >> 12) & 0x0F;
      int d2 = (x >> 8) & 0x0F;
      return d1 * 10 + d2;
    }
    
    public double GetMonth(double val)
    {
      ushort x = (ushort)val;
      int d1 = (x >> 4) & 0x0F;
      int d2 = x & 0x0F;
      return d1 * 10 + d2;
    }

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

    #23087
    manjey73
    Участник

    Офигеть, в примерах в десятичном виде 🙂 а если в HEX посмотреть то действительно BCD

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

    Непонятно, зачем разработчики контроллера усложняют жизнь инженеров.
    16.04 — в BCD использует 2 байта.
    16 (байт) + 04 (байт) также было бы 2 байта, если каждое число записать в полрегистра Модбас, но формула была бы проще.

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

    @vylegzhanind, какой это контроллер?

    #23107
    manjey73
    Участник

    Усложнения могут быть связаны с отображением на экране прибора например.

    #23127
    VylegzhaninD
    Участник

    это расходомер сточных вод ВоСток

    #23128
    VylegzhaninD
    Участник

    Все формулы которые мной использовались ранее я вводил прямо в строке столбца «Формула» во входных каналах или каналах управления.
    В этот раз я задаю в «Справочники» — «Формулы»
    Номер: 13
    Наименование: BCD
    Исходный код: копирую из сообщения #23086

    Далее во входных каналах в «формула» пишу «BCD» и ставлю флаг использовать формулу. Так ли это надо сделать или как-то иначе?

    По результату манипуляций Кп не работает.

    #23129
    a80808
    Участник

    Ну во первых там две формулы — GetDay(val) и GetMonth(val). Соответственно и в таблице Скриптов тоже должно быть их две.
    Соответственно вызов формулы в канале должно выглядеть как
    GetDay(vvv)
    или
    GetMonth(vvv)
    В зависимости от того, что вы хотите получить в канале — день или месяц

    где vvvv — это то, что вы получаете от контроллера.

    Ну и смотрите Журнал сервера — там лог компиляции формул.

Просмотр 15 сообщений - с 1 по 15 (из 59 всего)
  • Вы должны авторизироваться для ответа в этой теме.