Просмотр полной версии : Посчитать количество сработавших дискретных входов ПЛК
Eugene Vavilov
28.09.2019, 23:00
Пожалуйста, подскажите новичку как программно более просто найти количество (изменяющееся) получивших лог. 1 (сработавших) дискретных входов. Чтобы вывести просто числовое значение на экран. Может есть более простой алгоритм, кроме "+1" к счёту, "-1" при отпускании... (Это просто для отображения количества неисправностей). Дальше нужно будет идентифицировать порядковый номер "неисправности", но это соображу.
К каждому входу привязать целочисленную переменную через преобразование Bool to int
Затем сложить все эти Int- ы
Если еще актуально, то я обычно использую методом расчета веса Хемминга. Давно где-то нашел алгоритм. За счет малого количества операций он значительно быстрей чем суммирование в цикле.
VAR
x: DWORD;
out: INT;
END_VAR
x:=%IB1.0+%IB1.1*256+%IB1.2*512+%IB1.3*1024;
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#55555555) + DWORD_TO_DINT((SHR(x,1) AND 16#55555555)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#33333333) + DWORD_TO_DINT((SHR(x,2) AND 16#33333333)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#0F0F0F0F) + DWORD_TO_DINT((SHR(x,4) AND 16#0F0F0F0F)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#00FF00FF) + DWORD_TO_DINT((SHR(x,8) AND 16#00FF00FF)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#0000FFFF) + DWORD_TO_DINT((SHR(x,16) AND 16#0000FFFF)));
out:=DWORD_TO_INT(x);
Считает надежно.
Если еще актуально, то я обычно использую методом расчета веса Хемминга. Давно где-то нашел алгоритм. За счет малого количества операций он значительно быстрей чем суммирование в цикле.
VAR
x: DWORD;
out: INT;
END_VAR
x:=%IB1.0+%IB1.1*256+%IB1.2*512+%IB1.3*1024;
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#55555555) + DWORD_TO_DINT((SHR(x,1) AND 16#55555555)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#33333333) + DWORD_TO_DINT((SHR(x,2) AND 16#33333333)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#0F0F0F0F) + DWORD_TO_DINT((SHR(x,4) AND 16#0F0F0F0F)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#00FF00FF) + DWORD_TO_DINT((SHR(x,8) AND 16#00FF00FF)));
x:=DINT_TO_DWORD(DWORD_TO_DINT(x AND 16#0000FFFF) + DWORD_TO_DINT((SHR(x,16) AND 16#0000FFFF)));
out:=DWORD_TO_INT(x);
Считает надежно.
При чем здесь суммирование в цикле?
VAR
NumInp: UINT;
END_VAR
NumInp:=BOOL_TO_INT(In1) + BOOL_TO_INT(In2) + BOOL_TO_INT(In3) + BOOL_TO_INT(In4) +
BOOL_TO_INT(In5) + BOOL_TO_INT(In6) + BOOL_TO_INT(In7) + BOOL_TO_INT(In8);
И все - всего одна строчка кода!
45302
Код универсальный и работает на любое количество входов от 1 до 32. Оформляете как функцию (без первой строки) и считаете хоть входа контроллера, хоть входа модулей дискретных, хоть произвольные переменные, в которых нужно посчитать количество единичек.
Я только ошибся в первой строке, где идет преобразование входов в число:
x:=%IB1.0+%IB1.1*256+%IB1.2*65536+%IB1.3*16777216
Правильно будет так.
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot