Showing posts with label nState4. Show all posts
Showing posts with label nState4. Show all posts

June 28, 2019

Символьная линковка через атрибуты

Данные железа связываются с переменными программной части через конфигурацию контроллера. Иногда это не удобно и хочется идти не от конфигурации, а от кода (Code First). Как пример, я взял линковку переменных, связанных с управлением движением сервоосей NC PTP. И еще, верните, пожалуйста, карту мапинга — она была бессмысленной, но красивой ↘


Атрибуты


Переменной можно дописать атрибут — это специальная строка, которая говорит системе, что с переменно нужно сделать дополнительные телодвижения. Атрибутов было мало — сейчас стало много. В случае сервоосей нас интересует атрибут TcNcAxis:

{attribute 'TcNcAxis' := 'Axis 3'}
axMaster : AXIS_REF;

Здесь атрибут (ключевое слово attribute) заключен в фигурные скобки. Строка атрибута должна идти перед объявлением переменной или экземпляром функционального блока. Далее в кавычках следует одно или несколько(!) имен переменных или ФБ, символ присваивания  := , и наконец значение атрибута. В данном случае значением служит имя NC оси взятое из конфигурации  'Axis 3' . Записывается прямо с пробелами и другими символами, для этого и нужны кавычки.

Добавив атрибут и пересобрав проект, я автоматически получу слинкованную с сервоосью переменную типа AXIS_REF. Остается только реактивировать конфигурацию в ПЛК и все готово. Еще раз:
  1. Добавить строку атрибута или заменить имя оси в значении атрибута на другое.
  2. Пере/собрать проект (Build → Rebuild Solution).
  3. Активировать конфигурацию. Внимание! Активировать конфигурацию!
После активации, слинкованные через атрибут переменные будут подсвечены синим значком линковки (см. FromPlc и ToPlc):


Когда системе не удается слинковать данные, она сообщает об этом большим и внезапным сообщением поперек экрана. Проект в итоге соберется, но данные бегать не будут. Если же все прошло удачно, то после пересборки проекта система сообщит:
Message 06.01.2019 21:56:05 729 ms | 'TwinCAT XAE': Existing NC axis 'Axis 3' linked to instance 'MAIN.axMaster'
Очень удобно, так как теперь можно еще больше сконцентрироваться на коде. Главное не забывать пересобирать проект, а затем активировать конфигурацию. Аналогично можно работать с функциональными блоками.


Ввод/вывод


Переменные ввода/вывода также удобно линковать со стороны кода. Причем, здесь мы как раз увидим тот самый обещанный символьный маппинг во всей красе, так как будем использовать сложный символьный путь к данным.

На этот раз воспользуемся атрибутом TcLinkTo. Вообще, он простой, поэтому я возьму что-нибудь посложнее TcLinkToOSO. Атрибут c -OSO на конце позволяет не просто связать переменную типа AT %IQ* с данными, но также задать количество разрядов тут и там, а также их битовое смещение.

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

Напомню задачу: в настройках NC оси, в ветке конфигурации Axis X → Drive → Inputs →... есть поле nState4. Седьмой бит этого поля отвечает за быстрый останов данной сервооси. Пара битов этого поля уже автоматически слинкована с какими-то данными, поэтому действовать нужно аккуратно.
Быстрый стоп не работает на виртуальных осях! Необходимо серво-железо.
Для начала сходим в конфигурацию и посмотрим, где расположены требуемые данные в конфигурации со стороны железа, то есть смотрим во вкладку Variable, текстовое поле Full NameTINC^NC-Task 1 SAF^Axes^Axis 3^Drive^Inputs^In^nState4. Это полный путь к данным переменной nState4 в конфигурации:


Копируем и вставляем его в код программы как значение атрибута

{attribute 'TcLinkToOSO' := '<0,1,7>TINC^NC-Task 1 SAF^Axes^Axis 3^Drive^Inputs^In^nState4'}
cmd_FastStop AT %Q* : BOOL;

Мне нужен всего-лишь один бит, поэтому я расширил путь специальным суффиксом -OSO: <0,1,7>. Последовательно слева-направо:
  • 0 — битовое смещение в переменной ПЛК, то есть с какого бита ПЛК переменной начинать связывать. Можно связать не всю переменную, а только ее часть и не обязательно с начала и до конца: с помощью -OSO можно выхватить кусочек из середины.
  • 1 — количество связываемых бит.
  • 7 — битовое смещение в переменной на стороне железа (в моем случае в переменной nState4). Мне нужен бит номер 7, поэтому смещение = 7.

После сборки проекта система сообщает:
Message 06.01.2019 22:11:15 930 ms | 'TwinCAT XAE': Variable 'MAIN.cmd_FastStop' (Offs: 0) linked with 'TINC^NC-Task 1 SAF^Axes^Axis 3^Drive^Inputs^In^nState4' (Offs: 7, Size: 1)

Разбавлю полным листингом программы:

PROGRAM MAIN
VAR
    {attribute 'TcNcAxis' := 'Axis 3'}
    axMaster     : AXIS_REF;
    
    McPower      : MC_Power;
    McVelocity   : MC_MoveVelocity;

    cmd_PowerOn  : BOOL;
    cmd_Velocity : BOOL;
    {attribute 'TcLinkToOSO' := '<0,1,7>TINC^NC-Task 1 SAF^Axes^Axis 3^Drive^Inputs^In^nState4'}
    cmd_FastStop AT %Q* : BOOL;
    
    actVelo      : LREAL;
    state        : INT;
END_VAR

[...]

axMaster.ReadStatus();
actVelo := axMaster.NcToPlc.ActVelo;

CASE state OF
0:
    IF McPower.Status THEN
        cmd_Velocity := TRUE;
        state := 100;
    END_IF

100:
    IF McVelocity.InVelocity THEN
        cmd_Velocity := FALSE;
        state := 200;
    END_IF
    
200:
    IF actVelo < 0.1 OR NOT McPower.Status THEN
        cmd_PowerOn := FALSE;
        state := 300;
    END_IF     
    
300:
    IF NOT McPower.Status THEN
        cmd_FastStop := FALSE;
        state := 0;
    END_IF

END_CASE

McPower(
    Axis            := axMaster, 
    Enable          := cmd_PowerOn, 
    Enable_Positive := TRUE, 
    Enable_Negative := TRUE
);

McVelocity(
    Axis     := axMaster, 
    Execute  := cmd_Velocity, 
    Velocity := 200
);

Теперь если во время работы программы дернуть за булевый флаг cmd_FastStop и установить его в TRUE, мы незамедлительно получим быструю остановку сервооси, а система подскажет нам, что:
Message 06.01.2019 22:23:25 772 ms | 'TCNC' (500): 'Axis 3' (Axis ID: 3) <NOTE>: 'Fast axis stop' triggered by IO interrupt 'Drive->Status4->Bit7' (SignalType=1 (SignalType_RisingEdge), FastDec=0.000000, FastJerk=0.000000, IoState=1, OldIoState=0)!

Мышой проще


А еще есть кнопка Link To PLC... которая никакого отношения к символьной линковке не имеет, зато позволяет присобачить одним кликом мыши переменную AXIS_REF к NC оси, и безо всяких там NcToPlc, PlcToNc, ...


February 27, 2019

Быстрый стоп и как линковать биты и булы

Есть кнопка Пуск, а есть Стоп. На минуту представьте себе большую и толстую центрифугу, которая разгоняется в течении нескольких минут. Как прервать выполнение команды NC, когда команда все еще пытается, но еще не достигла результата?

Вообще, в большинство команд NC PTP встроен параметр BufferMode, позволяющий стыковать два задания или, проще говоря, создать плавный переход от одного задания к другому. В том числе и для MC_Halt (останов движения), который может быть вторым в цепочке заданий. К сожалению, проблему это не решает — момент остановки по прежнему непредсказуем, а выглядеть это будет, как заторможенная реакция системы на реакцию кнопки "стоп".

Если же вы смелы и отважны, и вас не пугает останов с последующим сбросом ошибки, то можно кое-как выкрутиться и с помощью MC_Halt, но как-то это всё не красиво и хочется нормального решения без ошибок. Давайте определимся с заданием — необходимо остановить "толстую" центрифугу из любого состояния: не мгновенный стоп за кратчайший промежуток времени, а просто быстрый останов без ошибок, из любого состояния системы, независимо от выполняемой команды и прочее, прочее, прочее.


Fast Axis Stop


Ситуация, в которой останов происходит как можно ранее и желательно быстрее, описана в справочной системе Fast Axis Stop. Правда, в статье не хватает описания некоторых возможных побочных эффектов. А всё потому, что их просто — нет! Всё, дальше можно не читать.

В настройках NC оси есть специальный параметр nState4 типа USINT (он же UINT8 или просто BYTE). Седьмой бит (7..0) этого параметра управляет быстрым остановом. Система у нас дискретная, поэтому перед работой можно и нужно определиться с типом управляющего сигнала: передний фронт, задний, активный/неактивный, отключено/не отключено, ... то есть как и когда будем "дергать" бит управления. Все это задается в настройках NC оси:


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


Линковка переменных


В программе необходимо завести переменную ввода-вывода, через которую будем управлять функцией быстрого останова. Для управления достаточно одноразрядной переменной типа BOOL. Затем связываем переменную с параметром NC: FastStop AT %Q* : BOOL;

Здесь появляется первый нюанс — два бита восьмиразрядного параметра nState4 уже связаны с какими-то там переменными. Вы не увидите этого, пока работаете с виртуальными осями и мгновенно столкнетесь, когда будете работать на реальном "железе". Для проверки я буду использовать дополнительные задачи Additional Tasks или просто Tasks в модном TwinCAT 3, но все-равно учту, что линковать нужно несколько переменных одновременно.

В ветке проекта Tasks, создаем дополнительную задачу с произвольным названием: Add new item... → TwinCAT Task With Image. Под веткой Output переменных создаем переменную типа BOOL или BIT. Позже попробуйте поэкспериментировать с многоразрядными типами типа BYTE или WORD: это тоже интересно в плане частичной линковки переменных и параметров.


Теперь нужно добраться до параметра nState4: Motion → SAF → Axes → Axis N → Drive → Inputs → In. Добавляем линк к трём параметрам сразу, и помогает нам в этом клавиша Ctrl, и ряд параметров фильтра переменных (Show Variables и Show Variable Types):


Главная проблема в том, что параметр nState4 типа BYTE (USINT, UINT8) и, следовательно, он восьмиразрядный, а нам от него нужен всего-лишь один бит. Поэтому при линковке параметров разного типа на экран вываливается специальный диалог Variable Type Mismatch (несовпадение типа переменной) и начинается диалог с разработчиком:


  • Size — размер переменной в битах.
  • Offset — смещение в битах от начала переменной (31..23..15..7..0). Обратите внимание, счет ведется от нуля, поэтому в счете фигурируют не восьмёрки, а семёрки.

  • Own Variable — переменная или параметр, в которую разработчик ткнул мышкой. Есть разница с какой переменной начинать.
  • Linked Variable — переменная, к которой мы будем приклеиваться.
  • Overlapped — перекрытие или сколько бит от переменной нужно взять. Не обязательно пристёгивать все разряды, можно ограничиться каким-то определенным числом разрядов.

nState4 — параметр длиной 8 разрядов. Для линковки с переменной FastStop нам нужен только 7-й разряд, соответственно, для WcState — необходим нулевой разряд, для InputToggle — первый бит. Что и отражено в колонке Offset строки Own Variable.

Картинка с Main.fastStop (правый-нижний угол) дана для наглядности. Именно так, оно бы выглядело в реальной программе.


Стоп с блокировкой


Для останова движения в NC PTP есть два вида функциональных блоков MC_Halt и MC_Stop. Первый просто понижает текущую скорость до нуля; второй же, блокирует все операции на оси до тех пор, пока ось не остановит движение, а затем будет ждать пока разработчик не снимет блокировку. Это надежно, но непонятно, как в этом случае поведет себя функция быстрого останова.

А поведет она себя — как обычно: прервет функцию и как-то по своему быстро остановит ось. И никаких ошибок. Первый график показывает обычный стоп с блокировкой оси:


Горб на правом склоне второго графика, живописно демонстрирует процесс быстрого останова.


Уголок антиквара


В TwinCAT 2 всё аналогично: