Стартовая страница › Форумы › Понять, как работает ПО › Формулы › Операции с бинарным числом
- В этой теме 22 ответа, 4 участника, последнее обновление 1 год, 10 месяцев назад сделано
Mikhail.
-
АвторСообщения
-
16.08.2024 в 11:59 #34063
Alexandr
УчастникВсем добрый день!
Не подскажите, может ли Скада, используя базовые настройки работать с бинарным числом, а также отрезать не нужные.
к примеру, опрашиваю регистр 40001 с вариантом битов
бит 0 — ввод 1, напряжение вне диапазона
бит 1 — ввод 1, напряжение в диапазоне
бит 2 — ввод 2, напряжение вне диапазона
бит 3
бит 4
бит 5
и т.д.Использовать десятичное число когда так много статусов в одном регистре очень не удобно, больше путаешься, так как вариаций может быть много, и десятичное число будет от этого меняться.
Идея следующая,
получаю регистр в десятичном формате, перевожу его в бинарный, а далее
создаю расчетные каналы по количеству битов в регистре, и в расчетном канале нужно оставить только тот бит который отвечает за статус того или иного состояния, все остальные биты по хорошему убрать, что бы не запутаться.
В итоге получим что расчетный канал будет иметь значение либо 0 либо 1, что на много удобнее использовать в работе чем десятичные цифры.Если кто так делал, подскажите как у Вас выполнено.
За ранее спасибо!
16.08.2024 в 12:38 #34066
a80808УчастникЕсть функции GetBit() — получить значение бита и SetBit() — установить значение бита.
16.08.2024 в 13:20 #34070
MikhailМодераторДобрый день!
10-тичная, 16-ричная, двоичная форма — это касается только отображения чисел. Все числа в компьютере хранятся в двоичном виде.Битовые операции поддерживаются. Вы можете создать расчётные каналы и с помощью указанных выше формул взять нужный бит. Параметры формул есть в документации.
16.08.2024 в 13:32 #34073
a80808УчастникНу например:
Слово состояния в канале 100.
Создаем расчетный канал 1000. Пишем в нем формулу GetBit(Val(100),0)
В этом случае канал 1000 будет иметь значение 0 при норме напряжения и 1 при выходе за пределы.
И так далее…16.08.2024 в 14:45 #34074Alexandr
УчастникСпасибо,
а если требуется получить к примеру 4 бита из 16-ти, такое возможно?
16.08.2024 в 14:47 #34075
a80808Участник4 формулы в 4 канала потом по логическому ИЛИ в 5-й канал
16.08.2024 в 15:30 #34076Alexandr
УчастникСпасибо!
Примерно понимаю что нужно сделать.
Всем большое спасибо за помощь!
16.08.2024 в 16:49 #34077
manjey73УчастникБуквально недавно делали формулу на биты но по маске, нпприпер если надо сразу 3 бита вытащить.
Например для случаев, когда код ошибки формируется несколькими битами, а не одним.
16.08.2024 в 18:11 #34078Alexandr
УчастникА не могли бы скинуть пример, как Вы это осуществили.
у меня как раз такая же задача.
Регистр определяет 4 аварии, имеет 16 бит, соответственно разделен на 4 группы.
Каждая группа из 4 бит, определяет имеется ли аварийное сообщение на контроллере или нет.
16.08.2024 в 18:41 #34079
manjey73УчастникТак у вас каждый бит это какая-то авария.
А там было десятичное число, но в группах. По этому и делали смещение и вытягивание числа.В вашем случае просто GetBit вроде достаточно.
18.08.2024 в 13:19 #34085Alexandr
УчастникДобрый день,
Все верно, в поставленном вопросе у меня каждый бит в регистре определяет значение.
Когда я разобрался в данном вопросе, я вернулся к старым своим решениям, и захотелось навести там порядок, так как там я сделал это не совсем хорошо, я генерировал аварию и записывал десятичное значение, но если мы получим 2 аварии в одном регистре скада не выдаст проблему.
Контроллер Deep Sea для генераторов, в регистре аварий имеет 16 бит, в одном регистре 4 аварийных сообщения. Т.е. на каждую аварию предоставляется 4 бита.
Поэтому попросил у вас пример как делали вы с тремя битами, и сделать что то подобное с 4-мя битами.
Хотел бы сделать просто все верно и красиво.18.08.2024 в 13:38 #34086
manjey73УчастникВот делали формулу вытаскивания сразу нескольких бит по маске. Она достаточно гибкая, при маске, равной по умолчанию 1 по сути это тот же GetBit
возвращает так же double, суть убрать лишние выставленные биты в числе, которые не нужны
-
Ответ изменён 1 год, 10 месяцев назад пользователем
manjey73.
19.08.2024 в 08:42 #34089Alexandr
УчастникВсем добрый день!
manjey73, я посмотрел по ссылке, но что то у меня ничего не получается, сервер не стартует, не могли бы Вы помочь.
Как писал ранее в регистре 16 бит, по 4-е бита на каждую аварию.
к примеру
Name Min Max Bits/ Sign
Emergency stop 0 15 13/16-16/16
Low oil pressure 0 15 9/16-12/16
High coolant temperature 0 15 5/16-8/16
Reserved 0 15 1/16-4/16Я добавил в скрипты Вашу формулу
public double GetAnyBits(double val, int n, int mask = 1)
{
ulong ulVal = (ulong)val;
return (ulVal >> n) & (ulong)mask;
}Для получения старший 4 битов (первые четыре слева) Emergency stop мне требуется выполнить смещение в право на 8, но я не понимаю что за маска. Это какое число от чего они зависит? не могли бы подсказать?
А если мне требуется получить 4 бита High coolant temperature, смещение вправо на 4, а первые 8 битов они отрежутся?
19.08.2024 в 09:46 #34091Alexandr
Участникmanjey73
я разобрался со сдвигами, и масками.
Всем огромное спасибо за оказанную помощь.
-
Ответ изменён 1 год, 10 месяцев назад пользователем
Alexandr.
19.08.2024 в 11:05 #34093
manjey73УчастникНу маской может быть и число 01010101 в бинарном виде и смещать ничего не придется 🙂
а так да, если нужны 4-ре бита, вы их смещаете к нулевому биту, то маска будет 15.
Если нужны 3 бита, то маска 7 и так далее, как нравится. -
Ответ изменён 1 год, 10 месяцев назад пользователем
-
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.