SIEMENS, DF&PD

Предыдущее посещение: Вс июл 10, 2016 18:33 Текущее время: Вс июл 10, 2016 18:33

Часовой пояс: UTC + 3 часа




 [ Сообщений: 23 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Посчитать количество активных бит
СообщениеДобавлено: Пн дек 02, 2013 15:44 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
Добрый день.

Стоит задача посчитать количество включенных исполнительных устройств. Есть бит статуса, который выставляется в 1 если устройство включено, и в 0 если устройство выключено.

В связи с тем что планируется несколько установок с различным количеством исполнительных устройств ( от 4 до 25) хочется написать универсальную функцию на вход которой подать биты статусов, а на выходе получить число включенных устройств.

Вопрос первый - в TIA Portal V12 для контроллеров S1200 есть функции MIN и MAX где количество входов можно наращивать по желанию - т.е. надо 3 числа сравнить - делаем три входа, надо 10 - делаем 10 входов - есть ли возможность сделать такой же фунционал у пользовательских блоков, или мне следует ориентироваться сразу на максимально возможное количество устройств?
Поясню для чего нужно "сокрытие" неиспользуемых входов - для данных установок хочется написать несколько фунциональных блоков, реализующих базовые алгоритмы, из которых технолог в LAD диаграмме будет как из кирпичей собирать итоговую программу, поэтому блок с 25 входами будет занимать кучу пространства, а реально может понадобится только 4.

Вопрос второй - если мы функцию подсчета активных бит пишем так чтобы она могла работать в мультиэкземплярном режиме, то еслим мы хотим пробежать в цикле несколько отдельных дискретных входов нашей функции, то смотреть надо в сторону косвенной адресации и работы с регистром AR2?

Ну и вопрос третий скорее философский - стоит ли вообще заморачиваться с подобным или сделать проще - завести глобальную переменную и инкрементировать/декрементировать ее по передним фронтам битов статуса?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 02, 2013 17:57 
Не в сети
Написал больше чем Вы читали

Зарегистрирован: Вс янв 29, 2006 10:01
Сообщения: 1932
Откуда: Портал razrab.ru
Уточните желаемое. Я понял так: допустим имеется слово из 16 бит, нужно подсчитать число включенных битов (выход функции - число от 0 до 16). Так?
Я писал функцию FC со входным параметром типа WORD и выходным параметром типа BYTE. Каждый включенный бит входного слова инкрементирует выход. То есть применяется 16 операций INC. В начале функции надо не забыть обнулиться. Контроллер S7-1200.
Самое главное - уметь работать с FC и с ее параметрами типа INPUT и OUTPUT.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн дек 02, 2013 21:42 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
Михайло писал(а):
Уточните желаемое. Я понял так: допустим имеется слово из 16 бит, нужно подсчитать число включенных битов (выход функции - число от 0 до 16). Так?
Я писал функцию FC со входным параметром типа WORD и выходным параметром типа BYTE. Каждый включенный бит входного слова инкрементирует выход. То есть применяется 16 операций INC. В начале функции надо не забыть обнулиться. Контроллер S7-1200.
Самое главное - уметь работать с FC и с ее параметрами типа INPUT и OUTPUT.


В качестве входных данных в идеале - несколько битовых величин, т.е. на Input1 подается флаг состояния 1 исполнительного механизма, на Input2 подается флаг состояния 2 исполнительного механизмa и так далее. Т.е. в качестве входныхх данных N входов типа BOOL. По идее эти флаги берутся из DB устройств.
Их конечно можно предварительно упаковывать в слово, но делать этого не хочется, т.к. тогда теряется универсальность ради которой все затевается. Хочется чтобы фунция была конфигурируемой под необходимое количество входов - пример идеала я привел - функции MIN и MAX в портале для S1200 - они позволяют нарастить количество аргументов до необходимого ( максимум 99 аргументов ). Вопрос именно в возможности такого наращивания - возможно да/нет?
Если возможно то как это сделать?

Если невозможно тогда понятен следующий путь - делаем FB под 99 (ну или ограничиваем разумным количеством, в моем случае 25 устройств => 25 входов) входов, в качестве значения по умолчанию всем false. В цикле пробегаем входы, и если они true то инкрементируем на 1. И вот тут второй вопрос - чтобы пробежать в цикле входы (все равно на чем пишем STL/SCL) нам скорее всего потребуется косвенная адресация и работа с регистром AR2 (тут могу ошибаться - с косвенной адресацией пространства входов функционального блока до этого дела не имел, и спрашиваю у знатоков - так ли это).
Решать задачу "в лоб" 25 скопировав проверку бита и инкрементирование переменной можно но нехочется - это экстенсивный путь, и идя по нему ничего нового не узнаешь и тратишь силы на совершенно рутинные операции.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 6:18 
Не в сети
Известный Писатель

Зарегистрирован: Вт янв 20, 2009 13:44
Сообщения: 343
Код:
      L     0
      A     #in1                        // bool
      JCN   _02

      INC   1
_02:  A     #in2                        // bool
      JCN   _03

      INC   1

// и тд. до 32
_03:  T     #Out                        // int


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 9:52 
Не в сети
Новый писатель

Зарегистрирован: Пт авг 09, 2013 9:36
Сообщения: 14
Попробуйте использовать функцию PEEK_BOOL (Basic Instruction->Move operation). Создайте DB. В атрибутах DB снимите галочку Optimized block access. В DB создайте структуры по 8 бит. В цикле проверяйте каждый бит. В начале не забывайте сбросить счетчик.
Должно получиться что-то типа такого:
Код:
#Counter := 0;
FOR #Byte := 0 TO #LastByte BY 2 DO
    FOR #Bit := 0 TO 7 DO
        #Bool := PEEK_BOOL(area:=16#84, dbNumber:=#NmbDB, byteOffset:=#Byte, bitOffset:=#Bit);                                    IF #Bool THEN #Counter := #Counter + 1; END_IF;
    END_FOR;
END_FOR;

#LastByte - адрес последней структуры в DB.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 10:33 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
ProFan писал(а):
Код:
      L     0
      A     #in1                        // bool
      JCN   _02

      INC   1
_02:  A     #in2                        // bool
      JCN   _03

      INC   1

// и тд. до 32
_03:  T     #Out                        // int


Это как раз путь по которому я НЕ ХОЧУ идти, о чем я писал выше. В случае если мне потребуется проверять 100 бит что делать? 200? Тоже вручную создавать? А если мне в проекте требуется ( а ведь реально требуется ) посчитать количество бит для разных параметров - то под каждый подсчет делать отдельную функцию?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 10:35 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
vovtenint писал(а):
Попробуйте использовать функцию PEEK_BOOL (Basic Instruction->Move operation). Создайте DB. В атрибутах DB снимите галочку Optimized block access. В DB создайте структуры по 8 бит. В цикле проверяйте каждый бит. В начале не забывайте сбросить счетчик.
Должно получиться что-то типа такого:
Код:
#Counter := 0;
FOR #Byte := 0 TO #LastByte BY 2 DO
    FOR #Bit := 0 TO 7 DO
        #Bool := PEEK_BOOL(area:=16#84, dbNumber:=#NmbDB, byteOffset:=#Byte, bitOffset:=#Bit);                                    IF #Bool THEN #Counter := #Counter + 1; END_IF;
    END_FOR;
END_FOR;

#LastByte - адрес последней структуры в DB.


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 10:47 
Не в сети
Новый писатель

Зарегистрирован: Пт авг 09, 2013 9:36
Сообщения: 14
Какие именно телодвижения вас смущают?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 11:30 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
vovtenint писал(а):
Какие именно телодвижения вас смущают?


По спокойному размышлению понял, что ничего не смущает, в голове была определенная идея, на которой зациклился. Впрочем ниже будет решение, к которому пришел я.

Если кратко то я хотел пройтись по входам, блока и сформировать результат + у меня вложенные вызовы FB, и чтобы не плодить количество DB сделал мультиэкземплярный вызов.

Ваш же способ подразумевает однократное создание DB, ее инициализацию перед началом работы функции, вызов функции, получение значений, сохраняем значения. Дальше при следующем вызове в другом месте мы опять инициализируем DB и запускаем функцию. Ваш метод проще и к тому же оптимальнее по памяти. Спасибо еще раз, мозги встали на место :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 11:31 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
Собственно решение без проверок, так сказать чистый Proof of Concept:

Код:
      L     0 
      T     #Val   
      L     #Count
      T     #index
      TAR2
      AD    DW#16#00FF_FFFF
      LAR1  P#DIX0.0
      +AR1

_CMP: L     #index
      L     0
      >I
      JCN   _OUT

      A [ AR1 , P#0.0 ]
      JCN   _DEC
      L     #Val
      INC   1
      T     #Val

_DEC: L     #index
      DEC   1
      T     #index

      +AR1  P#0.1
      JU    _CMP

_OUT: L     #Val
         T     #Out



Входы: сначала идут данные входов ( у меня это несколько входов типа BOOL, но подозреваю, что код перемолотит и несколько идущих подряд переменных других типов)
параметр #Count типа Int который определяет сколько значений мы будем проверять, по идее его можно не передавать, а просто пробегать максимальное количество значений
Выходы: #Out типа Int
Временные переменные: #Val, #index типа Int

Как все это работает:


Код:
      TAR2
      AD    DW#16#00FF_FFFF
      LAR1  P#DIX0.0
      +AR1


Здесь мы получаем начальный адрес входов. Для этого командой TAR2 грузим в аккумулятор индексный регистр AR2. Там при вложенном мультиэкземплярном вызове FB находится внутризонный указатель нашей структуры данных, ассоциированной с вызовом FB.
Поскольку нам нужен только адрес, а в в двух старших битах содержится добавочная информация , осуществляем маскирование командной AD DW#16#00FF_FFFF.
Командой LAR1 P#DIX0.0 загружаем в индексный регистр AR1 указатель на адрес входных параметров блока.
Добавляем содержимое аккумулятора к регистру AR1 командой +AR1 и получаем в регистре AR1 начальный адрес наших входов.

В случае если нам не нужна мультиэкземплярность то пишем просто
Код:
   LAR1  P#DIX0.0


В дальнейшем мы осуществляем проверку бита командой:
Код:
A [ AR1 , P#0.0 ]


и переходим к следующему биту командой:
Код:
   +AR1  P#0.1


Остальное должно быть понятно, но если требуются какие-то еще пояснения, или есть какие-то мысли - буду рад услышать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 13:56 
Не в сети
Известный Писатель

Зарегистрирован: Вт янв 20, 2009 13:44
Сообщения: 343
CountZero писал(а):
ProFan писал(а):
Код:
  +++    code   +++

Это как раз путь по которому я НЕ ХОЧУ идти, о чем я писал выше. В случае если мне потребуется проверять 100 бит что делать? 200? Тоже вручную создавать? А если мне в проекте требуется ( а ведь реально требуется ) посчитать количество бит для разных параметров - то под каждый подсчет делать отдельную функцию?
У вас было указано от 4 до 32 устройств. Функция пишется на определённое разумное количество устройство, а на не использованные входа функции присвоить константы или переменные с нулевым значением.
А вы хотите использовать косвенную адресацию для опроса 4 устройств! Да, сильное решение.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 14:46 
Не в сети
Написал больше чем Вы читали

Зарегистрирован: Вс янв 29, 2006 10:01
Сообщения: 1932
Откуда: Портал razrab.ru
Мой подход гибче всего. Вы можете создавать сколько угодно групп по 16 устройств максимум и будет всего одна функция, в которой будут всего 16 инкрементов по условию. :-P


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 15:36 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
ProFan писал(а):
У вас было указано от 4 до 32 устройств. Функция пишется на определённое разумное количество устройство, а на не использованные входа функции присвоить константы или переменные с нулевым значением.
А вы хотите использовать косвенную адресацию для опроса 4 устройств! Да, сильное решение.


Я хотел и хочу создать универсальную функцию, потому что она будет использоваться в различных установках и с различным количеством входных данных. И я не знаю как потенциально может расширится система в будущем.
Если мне завтра потребуется сделать 64 устройства то мне придется либо переписывать все-таки функцию заново, либо использовать многократно один и тот же блок, либо плодить разные варианты функций в системах в зависимости от количества устройств на системе - мне кажется это не очень правильным. Хочется некоторого единообразия в алгоритмических блоках на однотипных установках.
А рост накладных расходов на косвеснную адресацию меня не пугает - запас есть. И спорить с тем что ваш способ оптимальнее и по быстродействию и по памяти я не собираюсь - это очевидно.
Другое дело, что принимать решение об уместности использования косвенной адресации предоставьте пожалуйста мне. Когда и если мне потребуется заняться оптимизацией - я ей займусь.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт дек 03, 2013 15:45 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
Михайло писал(а):
Мой подход гибче всего. Вы можете создавать сколько угодно групп по 16 устройств максимум и будет всего одна функция, в которой будут всего 16 инкрементов по условию. :-P


Гибкой я называю функцию, если она без изменения кода может масштабироваться на необходимое количество аргументов у вас этого нет. Наращивание будет осуществляться за счет множественного вызова функции и суммирования полученных значений, мне этого хотелось избежать.

У меня складывается ощущение, что внимательно прочитать и осознать написанное в моих первых сообщениях смогли единицы. Остальные схватились за заголовок "посчитать количество активных бит" и принялось строчить ответы. Там даже вопросы выделены фразами "Вопрос первый", "Вопрос второй". Как мне казалось заданные вопросы подразумевают что человек представляет себе какими способами можно посчитать количество бит, у него есть некие задумки по реализации и он спрашивает про подробности именно данной конкретной реализации.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 4:29 
Не в сети
Написал больше чем Вы читали

Зарегистрирован: Вс янв 29, 2006 10:01
Сообщения: 1932
Откуда: Портал razrab.ru
Обижаешь. Мы решаем реальные проблемы, а не вчитываемся в то, что топик-стартер едва сумел настрочить и сам не понял, чего хочет. Ия уверен, что ты о сих пор не понял, чего хочешь. Пока понятно одно: ты хочешь помудохаться, чтобы твоя функция решала все задачи на свете, которые могут только попасться. Ну-ну... осталось дождаться этих гипотетических задач.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 5:37 
Не в сети
Известный Писатель

Зарегистрирован: Вт янв 20, 2009 13:44
Сообщения: 343
Не могли бы вы тогда уточнить нашей аудитории, на какое количество переменных рассчитана ваша функция? Или у неё нет конкретных цифр?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 8:22 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
Михайло писал(а):
Обижаешь. Мы решаем реальные проблемы, а не вчитываемся в то, что топик-стартер едва сумел настрочить и сам не понял, чего хочет. Ия уверен, что ты о сих пор не понял, чего хочешь. Пока понятно одно: ты хочешь помудохаться, чтобы твоя функция решала все задачи на свете, которые могут только попасться. Ну-ну... осталось дождаться этих гипотетических задач.


Чего я хотел я изложил, причем для неочевидных вещей я привел вполне конкретный пример поведения, более того я привел решение, которое полностью делает то что я хотел. Также,
vovtenint привел вариант который имеет необходимый мне функционал и по ряду признаков лучше моего решения. Идея вашей реализации, и реализация ProFan
понятна, очевидна, и в общем-то лежит на поверхности, только спрашивал я про несколько другое.

Если, открыть документацию, изучить ранее не используемые инструменты и механизмы, написать тестовую программу, получить подтверждение работоспособности конкретной идеи вы называете "помудохаться", тогда да, я хотел именно этого.
Не надо утрировать, про все задачи речи не шло. На реальной задаче, совсем не гипотетической, имеется 30 установок первой очереди и еще столько же во второй ( сколько их будет дальше я не знаю). Все эти установки имеют по сути одинаковый функционал, все установки имеют фиксированное число классов исполнительных устройст (вентиляторы, двигатели и т.п.), но по технологическим причинам количество исполнительных устройств на установках различается. В первой очереди самых маломощных число исполнительных устройств разнится от 4 до 25, что будет дальше - я не знаю. Я знаю одно, что поскольку алгоритмы работы установок не меняются, то мне как программисту требуется решить задачу в общем виде. Дальше в дело вступает технолог, который спараметрировав мои блоки получит итоговую программу, и чем меньше будет у технолога промежуточных действий, тем меньше у него будет шансов допустить ошибку, тем свою работу я считаю лучше выполненной.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 8:23 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
ProFan писал(а):
Не могли бы вы тогда уточнить нашей аудитории, на какое количество переменных рассчитана ваша функция? Или у неё нет конкретных цифр?


Для первой очереди это цифры от 4 до 25. Что будет во второй очереди и потом я пока не знаю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 8:43 
Не в сети
Известный Писатель

Зарегистрирован: Вт янв 20, 2009 13:44
Сообщения: 343
CountZero писал(а):
ProFan писал(а):
Не могли бы вы тогда уточнить нашей аудитории, на какое количество переменных рассчитана ваша функция? Или у неё нет конкретных цифр?

Для первой очереди это цифры от 4 до 25. Что будет во второй очереди и потом я пока не знаю.
Ладно, раз намёка вы не поняли, ваш алгоритм позволяет работать с числом устройств до 255, если их число превысит указанное число, ваш алгоритм будет не работоспособным. И простые советы вам давали не потому, что мы такие ограниченные, а только потому, что в простой реализации меньше ошибок можно совершить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср дек 04, 2013 11:05 
Не в сети
Новый писатель

Зарегистрирован: Пн дек 02, 2013 14:47
Сообщения: 43
Откуда: Санкт-Петербург
ProFan писал(а):
CountZero писал(а):
ProFan писал(а):
Не могли бы вы тогда уточнить нашей аудитории, на какое количество переменных рассчитана ваша функция? Или у неё нет конкретных цифр?

Для первой очереди это цифры от 4 до 25. Что будет во второй очереди и потом я пока не знаю.
Ладно, раз намёка вы не поняли, ваш алгоритм позволяет работать с числом устройств до 255, если их число превысит указанное число, ваш алгоритм будет не работоспособным. И простые советы вам давали не потому, что мы такие ограниченные, а только потому, что в простой реализации меньше ошибок можно совершить.


Мой алгоритм работоспособен и при количестве устройств больше 255, а вот реализация приведенная в качестве Proof of Concept действительно не работоспособна если мы зададим #Count больше 255 (я не случайно назвал свою реализацию так - это очень грубый прототип, запускать который на действующей системе крайне не рекомендуется).
Причиной неработоспособности является тот факт, что команды INC/DEC работают только с младшим байтом аккумулятора, собственно этим обуславливается тот факт, что мы можем задать в качестве параметра для этих команд числа от 0 до 255.

Если мы хотим использовать числа больше 255 то нам следует заменить последовательность:

Код:
  L     #Val
  INC   1
  T     #Val 

на
Код:
L     #Val
L     1
+I
T     #Val

и
Код:
L     #index
DEC   1
T     #index

на
Код:
L     #index
L 1
-I
T     #index

Все вышеприведенные объяснения адресованы не вам, а тем новичкам, которые могут просматривать эту тему.

С идеей о том, что в решении задачи надо отталкиваться от реальных данных и условий - я опять таки не спорю. Выше я уже пытался объяснить причину создания такой навороченной функции.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
 [ Сообщений: 23 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Перейти:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group