PDA

Просмотр полной версии : Посчитать количество сработавших дискретных входов ПЛК



Eugene Vavilov
28.09.2019, 23:00
Пожалуйста, подскажите новичку как программно более просто найти количество (изменяющееся) получивших лог. 1 (сработавших) дискретных входов. Чтобы вывести просто числовое значение на экран. Может есть более простой алгоритм, кроме "+1" к счёту, "-1" при отпускании... (Это просто для отображения количества неисправностей). Дальше нужно будет идентифицировать порядковый номер "неисправности", но это соображу.

SA104
29.09.2019, 07:24
К каждому входу привязать целочисленную переменную через преобразование Bool to int
Затем сложить все эти Int- ы

SBeaR
25.10.2019, 04:48
Если еще актуально, то я обычно использую методом расчета веса Хемминга. Давно где-то нашел алгоритм. За счет малого количества операций он значительно быстрей чем суммирование в цикле.


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);

Считает надежно.

petera
25.10.2019, 10:19
Если еще актуально, то я обычно использую методом расчета веса Хемминга. Давно где-то нашел алгоритм. За счет малого количества операций он значительно быстрей чем суммирование в цикле.


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

SBeaR
25.10.2019, 11:07
Код универсальный и работает на любое количество входов от 1 до 32. Оформляете как функцию (без первой строки) и считаете хоть входа контроллера, хоть входа модулей дискретных, хоть произвольные переменные, в которых нужно посчитать количество единичек.
Я только ошибся в первой строке, где идет преобразование входов в число:

x:=%IB1.0+%IB1.1*256+%IB1.2*65536+%IB1.3*16777216
Правильно будет так.