Showing posts with label управление движением. Show all posts
Showing posts with label управление движением. Show all posts

November 26, 2020

Компактные сервомодули ELM72xx

Линейка сервотерминалов расширилась до 16 ампер. ELM72xx предлагает прикоснуться к блестящему металическому корпусу компактного сервотерминала.

Изображение: Beckhoff Automation

Сервотерминалы устанавливаются на дин-рейке вместе с другими EtherCAT терминалами в общей линейке. Металлический корпус лучше рассеивает тепло. Кабели подключаются через разъемы: должно быть удобнее.

  • ELM7211 — 1 двигатель до 4.5 A (Irms).
  • ELM7212 — 2 канала по 4.5 A (Irms).
  • ELM722— один на 8 A (Irms).
  • ELM722— два по 8 A (Irms).
  • ELM723— тот самый единственный на 16 A (Irms).

Модули расчитаны на двигатели AM8100. Питание 48 вольт; 24В на половине мощности. Питание и обратная связь в одном кабеле — однокабельная технология. Можно подключить внешний тормоз, обратную связь (энкодер или резольвер) и внешний тормозной резистор. Цифровые входа поддерживают функцию Probe Unit.

TwinSAFE логика обеспечивает безопасность через простые функции STO/SS1 (Safe Torque Off / Safe Stop 1) поверх EtherCAT (FSoE, Safety over EtherCAT) или в рамках комплекса безопасности движения Safe Motion (IEC 61800-5-2 / ГОСТ Р МЭК 61800-5-2-2015).

Остается вопрос о рассеивании тепла: нужны ли опциональные вентиляторы для обдува блестящего металлического зада?

November 13, 2020

Атрибут TcNcAxis

Атрибут TcNcAxis линкует NC ось со стороны кода, автоматически изменяя конфигурацию ПЛК. Про этот атрибут уже было в символьной линковке через атрибуты. Здесь же будет пара-тройка нюансов.


Массивы

Большое количество осей удобно объединять в массивы. Массив осей можно линковать одним атрибутом:

{attribute 'TcNcAxis' := '[1]:=Axis X; [2]:=Axis Y; [3]:=Axis Z' }
axes: ARRAY [1..3] OF AXIS_REF;


В имени оси можно использовать пробел. Имя оси в атрибуте тоже записывается с пробелами. Количество пробелов должно совпадать и между буквами в имени, и в атрибуте. Axis⎵X и Axis⎵⎵X — это разные оси.

Если имя оси указано в атрибуте, но оси с таким именем нет, то в конфигурации будет создана новая ось.

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


Автомапинг функциональных блоков

Если нет доступа к внутренностям функционального блока, можно воспользоваться… атрибутом:

{attribute 'TcNcAxis' := '.axisZ:=Axis Z'}
fbFoobar: FB_Foobar;

[...]

FUNCTION_BLOCK FB_Foobar
VAR
    axisZ: AXIS_REF;
END_VAR

[...]

В одном программном блоке может быть несколько экземпляров функционального блока. Но можно слинковать оси только одного экземпляра ФБ. Нельзя линковать несколько переменных AXIS_REF с одной и той же осью. При компиляции система выдаст ошибку: 
Mapping conflict! Same data of 'TINC^NC-Task 1 SAF^Axes^Axis Z^Inputs^FromPlc' is written from different sources


July 1, 2020

Параметры NC осей

Параметры приводных проектов специально разнесены по нескольким местам. Во первых, они разбиты по слоям или, иначе говоря, по месту применения: железо (сервоусилитель) + NC + софт (PLC). Во вторых, так безопаснее: железо имеет свои железные настройки, а все остальное и мягкое — располагает своими собственными "крутилками" и "показометрами".

Изображение: Beckhoff Automation

Тем не менее из ПЛК-проекта можно программно изменить любые настройки любого слоя. Это не всегда очевидно, но добраться все-таки можно.


Железо


Я буду упрощать. Традиционно сервоусилитель разбит на три контура: контур тока, контур скорости и контур положения. Первый контур опирается на физические характеристики мотора и сервоусилителя. Второй и третий — это контуры, построенные вокруг тех или иных регуляторов скорости, положения, момента и тому подобное. Регуляторы типа ПИД, его модификации и возможно что-то экспериментальное. Что и как они регулируют и чем управляют, попробуйте догадаться по их названиям. После их настройки сервоусилитель готов принимать команды и крутить мотор в нужном направлении.


Унификация и абстракция


Моторы и сервоусилители бывают разные. А бывают не только моторы, но и просто исполнительные механизмы к которым прилеплена обратная связь. И такую штуку тоже желательно причесать под одну гребенку. В общем нам нужно абстрагироваться от конкретики исполнительного механизма. Поэтому дальше идет слой NC-сервиса. Он абстрагирует исполнительную систему так, что программе технологического процесса не нужно ничего знать о конкретике физических процессов в исполнительной системе. У NC есть свой набор настроек.

Кроме собственныъ настроек у NC-системы есть свой собственный контур управления, который может... делайте выводы сами:



Технологический процесс


Процессом управляет программа. Управление она делает с помощью исполнительных механизмов. Получается, что программа дергает за ручки и кнопки слоя абстракции NC. У программы есть какие-то свои пожелания, которые она передает в слой NC.
 
Приводную часть настраивает "приводник" - специалист своего дела, а программы пишет "программист" - он тоже специалист, но уже своего дела. Хорошо когда это один человек: сам настроил, сам запрограммировал. Тем не менее, после тонкой настройки железа, эти настройки лучше оставить в покое и больше не трогать. Правда бывает, что нужно и что-то подкрутить программно.


Крутим параметры


Предположим, изменился коэффициент масштабирования энкодера инкрементов-на-миллиметр. В лексиконе приводника - это Nc feed constant. На самом деле это настройка не слоя железа, а настройка слоя NC. Такое смешение сделано для удобства: приводник настраивает все низко-уровневые и средне-уровневые параметры движения и железа в одном месте. Программист же может управляет параметрами движения типа скорость-ускорение и подрегулировать динамику через NC. Опять-таки удобно.

На картинке как раз кусок железа Drive Manager'a, где смешались в кучу слои:


Привод можно донастраивать через SoE, CoE и пр. В параметры NC можно залезть через функциональные блоки типа MC_WriteParameter, предоставляемой библиотекой Tc2_MC2. Эти настройки не навсегда — при следущей загрузке параметры откатятся до значений заданных в конфигурации. Так сделано для безопасности.

Список всех доступных настроек содержится в перечисляемом типе MC_AxisParameter. Его интересно полистать пару минут, вчитываясь в комментарии типа: (* new since 1/2012 *) или ...- available in Tc3 *) — история как она есть.

Чтобы как-то повлиять на значение параметров в конфигурации, можно при каждом старте ПЛК-программы задавать новые коэффициенты. Так и приходилось делать в TwinCAT 2. Теперь уже не обязательно — в TwinCAT 3 появились функции типа MC_WriteParameterPersistent. Через них достаточно задать параметр один раз и его значение легко переживет перезапуск ПЛК. При активации новой конфигурации, эти значения будут заменены на значения из новой конфигурации.

Небольшой пример как пользоваться, но там и так все понятно:

October 24, 2019

Ручной тормоз AM8000

У моторов AM8000 есть опция в виде тормоза. Наличие тормоза указывает единичка в заказном номере мотора AM8000-xxx1-... (и ноль когда тормоз отсутствует). Тормоз управляется отдельной цепью 24 В и срабатывает (накладывается) автоматически при отключении модуляции: тупо прижимается пружиной. И наоборот, при работе оттягивается электромагнитом, освобождая вал двигателя. Намертво тормоз вал не вклинит, но аварийно затормозит (это чтоб не порвало всё к ... и не намотало железо на вал).

В новой прошивке сервоусилителей версии 2.10 появилась возможность подключить внешний тормоз к двигателю без тормоза. Включается через параметр P-0-0060 = 2 (External motor brake: currentless locked).

Редко-редко, а иногда и когда-как, тормоз нужно отключить почти вручную, то есть программно. Управление производится через параметр P-0-0060. Подробнее можно прочитать в Configuration and control of the motor brake, но я туда не полезу, а воспользуюсь удобным функциональным блоком FB_SoEAX5000SetMotorCtrlWord.
Внимание! Не стойте, и не прыгайте, не пойте, не пляшите там, где идет строительство, или подвешен груз. Ручная работа с тормозом чревата отрыванием конечностей и зажевыванием туловища механическими руками. Повязывайте банданы, носите бронекепки и соблюдайте ТБ.
Для работы с ФБ необходимы библиотеки Tc2_MC2 и Tc2_MC2_Drive. В остальном все просто, кроме тристабильного состояния тормоза: вручную наложен, вручную разблокирован и автомат (как повезет):

PROGRAM MAIN
VAR
    {attribute 'TcNcAxis' := 'Axis 1'}
    axis1: AXIS_REF;
    
    EN, SET, LOCK, UNLOCK: BOOL;
    
    mcSetMotorCtrlWord: FB_SoEAX5000SetMotorCtrlWord;
    mcPower: MC_Power;
END_VAR

mcSetMotorCtrlWord(
    Axis := axis1,
    Execute := SET,
    ForceLock := LOCK,
    ForceUnlock := UNLOCK
);

SET R= NOT mcSetMotorCtrlWord.Busy;

mcPower(
    Axis := axis1, 
    Enable := EN, 
    Enable_Positive := TRUE, 
    Enable_Negative := TRUE
);

Для работы с тремя состояними выделено два управляющих бита: ForceLock и ForceUnlock. Сочетанием этих флагов устанавливается текущее состояние тормоза. Вброс значений производится по переднему фронту входа Execute. Я свел все возможные значения в табличку:


Например, возврат тормоза в автоматический режим осуществляется одновременным сбросом флагов ForceLock|Unlock в FALSE и последующей установкой Execute в TRUE. После этого состояние тормоза будет определяться или наличием модуляции, или на уровне NC состоянием флага разрешения Enable в MC_Power, что, впрочем, одно и то же.

Если сервопривод обесточить, то при следующем включении режим тормоза автоматически возвращается к автоматическому. Это поведение по умолчанию. Поэтому еще точнее — его режим после включения определяется значением параметра P-0-0060 в стартап листе. В параметр P-0-0072 транслируются параметры тормоза из мотор-пула двигателей. Значение параметра P-72 можно перезаписать и заменить на другие, но свойства тормоза от этого не изменятся: параметры нужны только для автоматических расчетов внутри программы.

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, ...


May 24, 2019

Контроль состояния сервотерминалов EL7201

Что если силовое питание не подано, ось не активна и вдруг разорвать сигнал обратной связи? Что если оторвать провод силового питания? Как будет реагировать NC? Возможно ли вообще отследить такой тип аварий и как сбросить ошибку? Копну глубже в контроль состояния компактных сервоусилителей EL72xx, и начну с обратной связи.
Изображение: Beckhoff Automation

Обратная связь


Сервоось недееспособна, если отсутствует сигнал обратной связи. Необходимо регулярно вызывать функцию Axis.ReadStatus(), чтобы понять, что с ней происходит. В момент потери сигнала будет выставлен флаг Axis.Status.DriveDeviceError.

Так как работа сервомотора без обратной связи невозможна, самостоятельно этот флаг не сбросится и не "рассосется". После устранения причины аварии, ошибку нужно будет сбросить с помощью стандартной функции MC_Reset. Но это всё на случай, если ПЛК и сервомодули нельзя обесточивать на время ремонта, обслуживания или замены оборудования. Безопаснее выключить и включить снова.


Силовое питание


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

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

Слово состояния сервомодуля (6010:10 — Statusword) содержит два бита, отвечающие за ошибки и аварии. Это бит #3 Fault и бит #7 Warning: стр. 143, Index 6010 DRV Inputs. Поле Fault отвечает за аварии. Этот бит транслируется подсистемой NC в поле состояния оси DriveDeviceError. Именно его мы отслеживали в главе про обратную связь. Потеря обратной связи — это авария, но(!) отсутствие силового питания — это еще не авария, а просто ситуация требующая особого внимания. Поэтому — Achtung, т. е. Warning.

Флаг Warning также транслируется в NC, но он не доступен через параметры состояния NC-оси. Причина этого для меня не понятна, но я попробую добраться и до этого флага.

Начнем с того, что Statusword передается в PDO сервомодуля. Затем, оно автоматически линкуется с NC параметрами Axis.Drive.Inputs.In.[nState1..nState2], попутно разбиваясь на старший и младший байты. И всё. Далее эти байты используются где-то внутри подсистемы NC и недоступны разработчику.

Чтобы получить доступ к слову состояния, можно непосредственно постучаться в сервомодуль, то есть прочитать параметры через функции CANopen. Можно и по другому. Если немного погуглить (а это более качественный способ поиска информации по справочной системе), то обнаруживается интересная таблица с индексами:

TwinCAT Connectivity → ADS-Device-Documentation → ADS Interface NC → Specification "Index group" for NC ( ID [0x01...0xFF] ) → Specification Drive → "Index offset" specification for cyclic drive process data (Index group 0x7300 + ID).

Из таблицы не совсем понятно зачем всё это необходимо, но судя по названиям...


Читаем другие параметры


Читать будем через ADS. Для чтения параметров, перечисленных в "таблице", мы воспользуемся функцией ADSREAD из библиотеки системных функций Tc2_System. Для запуска функции понадобятся:
  • NETID — пустая строка, если читаем с того же локального ПЛК.
  • PORT — это стандартный порт NC-Task SAF = 501.
  • IDXGRP — индекс группы из таблицы = 0x7300 + ID, где ID - это номер оси NC; нумерация осей начинается с единицы, то есть первая ось получит индекс = 16#7301.
  • IDXOFFS — смещение из таблицы = 16#80.

В таблице доступ к параметру 16#80 помечен как "Write", но все относительно и зависит от точки зрения, поэтому я буду из него "Read". Осталось решить куда прочитать данные. По идее необходима некая структура данных, но есть ли она в стандартных библиотеках мне не известно, поэтому я создал парочку своих собственных DUT. Выглядят они почти как в той самой таблице из справочной системы:

TYPE EL7201_DriveInfoEx :
STRUCT
    nInData1    : DINT;
    nInData2    : DINT;
    StatusWord  : EL7201_StatusWord; // Axis.Drive.Inputs.In.[nState1..nState2]
    nStatus3    : BYTE;
    nStatus4    : BYTE;
    // optional : extended drive info, 40 bytes
    nInData3    : DINT;
    nInData4    : DINT;
    nInData5    : DINT;
    nInData6    : DINT;
    nStatus5    : BYTE;
    nStatus6    : BYTE;
    nStatus7    : BYTE;
    nStatus8    : BYTE;
    Reserved1   : DINT;
    Reserved2   : DINT;
END_STRUCT
END_TYPE

Для удобства использования сразу же разбиваю слово состояния на структуру из битовых полей:

TYPE EL7201_StatusWord  :
STRUCT
    ReadyToSwitchOn     : BIT;
    SwitchedOn          : BIT;
    OperationEnable     : BIT;
    Fault               : BIT;
    Reserved4           : BIT;
    QuickStop           : BIT; // inverse: true when switched off
    SwitchedOnDisabled  : BIT;
    Warning             : BIT; // Ex.: raise when Power Supply lost
    Reserved8           : BIT;
    Reserved9           : BIT;
    TxPDOToggle         : BIT; // selection/deselection via 0x8010:01
    InternalLimitActive : BIT;
    TargetValueIgnored  : BIT;
    Reserved13          : BIT;
    Reserved14          : BIT;
    Reserved15          : BIT;
END_STRUCT
END_TYPE

В таблице есть указание что структура EL7201_DriveInfoEx может быть длинной как в 12 байт, так и расширенная, длинною в 40 байт. В моем случае необходима расширенная структура. Остается прочитать данные:

axis               : AXIS_REF;
axDriveStatus      : EL7201_DriveInfoEx;
AdsReadDriveStatus : ADSREAD;

[...]

AdsReadDriveStatus(
    NETID    := '', 
    PORT     := 501,
    IDXGRP   := 16#7300 + axis.NcToPlc.AxisId,
    IDXOFFS  := 16#80,
    LEN      := SIZEOF(axDriveStatus), 
    DESTADDR := ADR(axDriveStatus), 
    READ     := TRUE);
 
IF NOT AdsReadDriveStatus.Busy THEN
    AdsReadDriveStatus(READ := FALSE);
END_IF


Примечание: Fault и Warning работают и соответственно устанавливаются/сбрасываются независимо друг от друга: один флаг никак не влияет на другой. Warning устанавливается и сбрасывается автоматически, поэтому нет способа повлиять на его состояние.


Уровень силового питания


Значение силового питания (12-50 Вольт) можно прочитать напрямую из сервомодуля. Адрес сервомодуля можно получить с помощью функции MC_ReadDriveAddress и структуры ST_DriveAddress:

Изображение: Beckhoff Automation

Значение уровня постоянно обновляется в параметре CoE 9010:12 — DC link voltage. Значение дается в милливольтах, поэтому 24 вольтам будет соответствовать значение 23932. Почему не 24000? Потому что — не точно.

Следующий кусок кода прочитает значение напряжения прямо из сервомодуля:

dcLinkValue : DINT;
AdsReadCoE  : ADSREAD;

[...]

AdsReadCoE(
    NETID    := '169.254.23.39.4.1', 
    PORT     := 1002,
    IDXGRP   := 16#F302,
    IDXOFFS  := 16#90100012,
    LEN      := SIZEOF(dcLinkValue), 
    DESTADDR := ADR(dcLinkValue), 
    READ     := TRUE);
 
IF NOT AdsReadCoE.Busy THEN
    AdsReadCoE(READ := FALSE);
END_IF


NETID — адрес EtherCAT мастера.
PORT — номер порта устройства, в данном случае — это сервомодуль EL7201.
IDXGRP — индекс группы сервиса ADS, отвечающего за работу с CANopen SDO.
IDXOFFS — индекс и смещение регистра CAN. Для упрощения в примере выше индекс не вычисляется, так как в шестнадцатеричной системе его легко сформировать вручную 9010-0012. Если интересно, чуть более подробно написано в посте Работа с CANopen из C# программы.

Когда пример готов, подключаю цифровой осциллограф к переменной dcLinkValue и получаю график "зарядки-разрядки". Здесь питание контроллера и силовое питание сервомодулей подается от одного 24 вольтового блока питания. Поэтому "потолок" на графике ~ 24000, а сервомодуль работает с половинной мощностью:

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

February 28, 2019

Профили сервотерминалов MDP и DS

В среде Бекхофф есть два вида сервотерминалов EL72x1-000x. С одной стороны они совершенно одинаковые по электромеханическим параметрам; с другой стороны, они отличаются: во-первых, цифрой в модели, во-вторых, названием профиля: MDP742 или DS402. Что выбрать? Ответ можно найти в статье Profile MDP 742 or DS 402.

Профили относятся к стандарту CANopen. Для полной ясности, EL72x1 внутри себя сидит на шине CAN, данные которой транслируются дальше на шину EtherCAT. Профили определяют номера индексов/смещений, порядок/структуру параметров, а также ряд других свойств словарей объектов CAN. Оба профиля и MDP742, и DS402 содержат одинаковые наборы параметров, отличающиеся индексами и названиями параметров. Я бы такому заявлению про "одинаковость" сильно не доверял, поэтому и полез разбираться.

Вывод простой: оба профиля имеют одинаковый набор функций, но различаются доступом к ним, поэтому и работать с ними придется по разному. Правда TwinCAT сильно скрывает это. Сконфигурировав дерево проекта, на уровне переменных программы ПЛК, вы с параметрами CAN случайно уже не столкнетесь, только намеренно.

DS402 относится к стандарту IEC61800-7-200 (CiA402). Функционально — это то же самое и полностью совместимое вплоть до машины состояния. Поэтому единственная причина его наличия в прайслисте — это совместимость с чужим оборудованием или для работы в составе чужого оборудования.

Если же говорить о выборе между профилями, MDP742 (Modular Device Profile) — это стандартное представление набора параметров CoE объектов EtherCAT модулей Бекхофф. Именно с таким профилем терминалы поставляются с завода Бекхофф. Получается, что если специальные требования совместимости с DS402 отсутствуют и разработчику без разницы какие там параметры и в каком они порядке следуют, нужно выбирать MDP742. Иначе говоря, если вы не работаете напрямую с параметрами CAN — выбирайте MDP. Если вам все-равно — выбирайте MDP.

Вообще, профиль можно сменить, загрузив в сервотерминал другой профиль. После замены профиля необходимо обновить EEPROM, ESI и не забыть про двигатели. Так как описание объектов CoE и операционный образ (process data) профилей различаются, то необходимо также заменить в проекте XML профиль двигателей.

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 всё аналогично:


September 2, 2018

Работа с CAM-профилями

Есть ли возможность корректировать CAM-профиль (таблицу кулачкового взаимодействия) на лету? Например, когда ПЛК-программа подставляет новые точки в профиль или изменяет уже имеющийся профиль прямо в процессе отработки.

Да, можно. В процессе отработки профиля, можно изменять не только координаты точек траектории, но и скорость, ускорение и рывок (jerk). Подставлять новые или удалять уже имеющиеся точки — нельзя, но можно исключить имеющиеся точки из траектории. В дальнейшем система будет игнорировать их, что будет выглядеть, как будто мы их удалили.
MC_MotionFunctionPoint .PointType : MC_MotionPointType := MOTIONPOINTTYPE_IGNORE
По мере необходимости, скрытые точки можно реактивировать заново, что можно расценивать, как добавление точек в траекторию. Необходимо заранее предусмотреть максимально необходимое число точек.

А что, если в ПЛК уже сидит какая-то сконфигурированная CAM-таблица, но мы хотим иметь возможность корректировать ее, то есть изменять профиль, причем, не залезая в конфигуратор и не реактивируя конфиг? Например, необходимо организовать полный доступ к CAM-таблице через интерфейс пользователя.

Новые профили (CAM-таблицы) можно создавать из ПЛК-программы в любое время, в том числе и во время исполнения текущей CAM-таблицы. Можно создавать таблицы в редакторе профилей, встраивать их как образцы в конфигурацию, а затем в рантайме редактировать их из ПЛК-программы. Также можно "на лету" переключаться между профилями/таблицами или запускать их друг за другом, выстраивая сложную траекторию из отдельных кусков простых.

Вообще, система не различает таблицы созданные в редакторе и созданные вручную из ПЛК-программы. Система различает таблицы по их номеру CamTableID : MC_CAM_ID. По сути, этот номер просто синоним для числа типа UDINT, который отражает номер таблицы среди всех доступных таблиц. Системе всё равно, где была создана таблица.

TYPE
    MC_CAM_ID : UDINT;
END_TYPE


Возникает вопрос, а нужен ли вообще редактор Cam Design Tools или можно как-нить обойтись и сэкономить? Как-нить можно, но ругают его в основном за стоимость.

Редактор крут и наворочен. Позволяет одним махом нарисовать и отредактировать не только кривую траекторию, но и задать скорости, ускорения, рывки в узловых точках, по сути доступен полный набор производных движения. Траекторию можно сглаживать всякими полиномами пятой степени и загружать их одним кликом, вместе с остальным проектом. Стоит это все 4,5К евро, что для многих ставит жирный крест на рисовании траекторий кулачковых механизмов, отправляя их в пешее путешествии за таблицами в Экселе.

Если нет лицензии на редактор, то таблицы из CAM-дезигнера будут доступны только до первого закрытия студии или PLC Control'а. После повторного открытия конфигурации или проекта, этих таблиц в проекте уже не будет — они пропадут. Аналогично, без лицензии эти таблицы не захотят выгружаться в контроллер. Рисовать можно, грабить караваны координат и тащить их в казематы Экселя — можно, сохранять проект для потомков или в ПЛК-задачу — нельзя.

Подытожим, если супер редактор — это дорого, то смотрите на создание таблиц вручную из ПЛК-задачи. Вся библиотека (и дизайнер) хорошо описаны в документации TwinCAT MC Camming. Поэтому дальше будем вытаскивать только нюансы.


Создание CAM-таблиц


Если вы создаете CAM-таблицу вручную, то вам необходима функция MC_CamTableSelect. Данные, предоставленные вами в функцию, передаются в NC, где создается новая CAM-таблица. Эта функция не нужна, если вы создали таблицу в дизайнере: можно сразу переходить к MC_CamIn.

Чего нет в документации, так это фразы, что функция CamTableSelect по сути создает новую таблицу. Если же таблица с таким номером уже существует, то старая таблица будет удалена и на ее месте создана новая. Вот кусок, отвечающий за этот процесс (находится в библиотеке TcMC2_Camming). Для удобства, я выделил ключевые слова:

(* delete old table (possibly existing)*)
STATE_INTERNAL_DELETE :
    fbAdsWrite( NETID   := TcMcGlobal.NCNETID_TCMC_CAM,
                PORT    := TcMcGlobal.NCPORT_TCNCCAMMING_TABLEFUNCTION,
                IDXGRP  := TcMcGlobal.Table.Functions.IDXGRP + CamTableID,
                IDXOFFS := TcMcGlobal.Table.Functions.IDXOFFS.DELETETAB,
                LEN     := 0,
                SRCADDR := 0,
                WRITE   := TRUE,
                TMOUT   := TcMcGlobal.tADSTimeOut);

    IF NOT fbAdsWrite.BUSY THEN
        IF NOT fbAdsWrite.ERR THEN
            (*next step*)
            iStateInternal := STATE_INTERNAL_CREATE;
        ELSE

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


Активация профиля и наоборот


MC_CamIn — занимается сцеплением подчиненной оси с мастер-осью, а прослойкой между ними служит таблица с индексом CamTableID. Можно рассматривать эту таблицу как электронный редуктор с программным коэффициентом передачи, который по ходу работы будет извлекаться из данной таблицы.

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

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

Если оси двигались до процесса расцепления, то после расцепки они сохранят свою скорость движения, но уже как независимые оси (например, остановка одной оси никак не повлияет на другую ось). Такое поведение очень похоже на поведение блока MC_MoveVelocity.


Последовательность выполнения функций


Для примера, простая последовательность действий выглядит как-то так:
  1. MC_CamTableSelect( CamTableID
  2. MC_SetCamOnlineChangeMode
  3. MC_Power (TRUE, Master
  4. MC_Power (TRUE, Slave
  5. MC_CamIn
  6. MC_MoveVelocity( Master
  7. ...технологический процесс
  8. MC_CamOut
  9. MC_Halt( Master
  10. MC_Halt( Slave
  11. MC_Power (FALSE, Master
  12. MC_Power (FALSE, Slave


Изменение параметров движения


Прежде, чем изменять параметры движения, то есть вносить изменения в CAM-таблицу, нужно договориться с системой — как и когда вы будете это делать. Для переговоров используется функция MC_SetCamOnlineChangeMode. Достаточно выполнить ее один раз с необходимым набором параметров. Например, задать ActivationMode = MC_CAMACTIVATION_ASSOONASPOSSIBLE и данные будут применяться на лету, как можно быстрее и в самый безопасный момент движения.

Перед изменением можно прочитать существующий параметры (если они уже загружены) с помощью функции MC_ReadMotionFunction. Функция прочитает все данные таблицы, либо только заданное количество, а если вы зададите больше, чем есть на самом деле, то не страшно — функция прочитает только то, что будет доступно, ошибок не будет.

Для доступа к данным отдельной конкретной точки, используется функция MC_ReadMotionFunctionPoint. Данные содержат не только координаты, но и много другой полезной информации. Начнем с PointIndex — это порядковый номер (индекс) точки в траектории. Индексы положительны, начинаются с 1 и далее идут без разрывов, с единичным шагом: 1, 2, 3, 4, 5, ... и никаких нулей для стартового индекса.

Индексы последовательны, но порядок обхода точек — произвольный. За это отвечает поле RelIndexNextPoint — это относительный индекс следующей вычисляемой точки траектории. По умолчанию, он равен 1, что означает — выполнять по порядку следования точек. Для последней точки в траектории относительный индекс = 0. Изменять относительный индекс "на лету" нельзя, так как этот параметр важен для предварительного обсчета траектории.

И последнее, но не менее важное поле, FunctionType. Оно задает функцию движения для формирования траектории и расчета промежуточных точек. По умолчанию, используется MOTIONFUNCTYPE_POLYNOM5_MM — гладкая траектория с интерполяцией полиномами 5-й степени. В дизайнере этому соответствует функция Automatic. Типу же Synchron соответствуют сплайны первой степени MOTIONFUNCTYPE_POLYNOM1.

Учитывайте, что при использовании MOTIONFUNCTYPE_POLYNOM5_MM (или Automatic) необходимы как минимум три активные точки в куске траектории, то есть нужна сама точка и по одной точке с каждой стороны от нее. Итого, три точки в куске. Точка считается активной, если она не игнорируется PointType <> MOTIONPOINTTYPE_IGNORE. Это важно, если вы используете механизм, описанный в самом начале поста.


Практикум


Я создал замкнутый, повторяющийся каждые 360° профиль. Для простоты, траектория разбита пятью точками на четыре кусочно-линейные интервала движения. Точка №5 совпадает с точкой №1. Не забывайте, вы ставите точки, а траекторию между ними рассчитывает система.



На самом деле, я сначала нарисовал график в дизайнере, а затем вручную перетащил данные в ПЛК-программу (см. Приложение ниже). В итоге, для подчиненной оси получился следующий график:


До позиции 21000 подчиненный отрабатывает заданный в CAM-таблице график. Я отрезал на картинке "пики" позиций, чтобы не загромождать иллюстрацию.

После 21000 я программно, с помощью MC_WriteMotionFunctionPoint, ставлю в игнор точку 2: следите как изменился график от 21000 до 23500. Начиная с 23500 (вторая зеленая линия), я ставлю в игнор точку 3: с 23500 по 25000 работают только точки 1, 4, 5.
Учтите, что непосредственно точки я не удаляю, а всего-лишь изменяю их тип на PointType := MOTIONPOINTTYPE_IGNORE.
После позиции 25000 я возвращаю сначала точку 2, а где-то ближе к 28000 и точку 3. Затем все повторяется. Прогоните в голове эту последовательность несколько раз и всё встанет на свои места.


Приложение


PROGRAM MAIN
VAR
    AxMaster         : AXIS_REF;
    AxSlave          : AXIS_REF;
    camTable2_Id     : MC_CAM_ID := 2;
    camTable2        : MC_CAM_REF;
    camTable2_Points : ARRAY[1..10000] OF MC_MotionFunctionPoint;
    
[...]

camTable2.ArraySize   := SIZEOF(camTable2_Points);
camTable2.pArray      := ADR(camTable2_Points);
camTable2.TableType   := MC_TABLETYPE_MOTIONFUNCTION;
camTable2.NoOfColumns := 1;
camTable2.NoOfRows    := pointsNumber;

FOR i := 1 TO PointsNumber DO
    camTable2_Points[i].PointIndex := i;
END_FOR

camTable2_Points[1].PointType         := MOTIONPOINTTYPE_MOTION;
camTable2_Points[1].FunctionType      := MOTIONFUNCTYPE_POLYNOM1; // 5_MM;
camTable2_Points[1].RelIndexNextPoint := 1;
camTable2_Points[1].MasterPos         := 0.0;
camTable2_Points[1].SlavePos          := 0.0;

camTable2_Points[2].PointType         := MOTIONPOINTTYPE_MOTION;
camTable2_Points[2].FunctionType      := MOTIONFUNCTYPE_POLYNOM1; //5_MM;
camTable2_Points[2].RelIndexNextPoint := 1;
camTable2_Points[2].MasterPos         := 100.0;
camTable2_Points[2].SlavePos          := 10.0;

camTable2_Points[3].PointType         := MOTIONPOINTTYPE_MOTION;
camTable2_Points[3].FunctionType      := MOTIONFUNCTYPE_POLYNOM1; //5_MM;
camTable2_Points[3].RelIndexNextPoint := 1;
camTable2_Points[3].MasterPos         := 150.0;
camTable2_Points[3].SlavePos          := 100.0;

camTable2_Points[4].PointType         := MOTIONPOINTTYPE_MOTION;
camTable2_Points[4].FunctionType      := MOTIONFUNCTYPE_POLYNOM1; //5_MM;
camTable2_Points[4].RelIndexNextPoint := 1;
camTable2_Points[4].MasterPos         := 250.0;
camTable2_Points[4].SlavePos          := 10.0;

camTable2_Points[5].PointType         := MOTIONPOINTTYPE_MOTION;
camTable2_Points[5].FunctionType      := MOTIONFUNCTYPE_POLYNOM1; //5_MM;
camTable2_Points[5].RelIndexNextPoint := 0; // последняя точка в траектории
camTable2_Points[5].MasterPos         := 360.0;
camTable2_Points[5].SlavePos          := 0.0;


На самом деле, красивее и проще это сделать через массивы или, что еще лучше, через чтение .csv файлов, содержащие данные CAM-таблицы.

January 26, 2017

Задание положения на лету

Можно ли сбросить значение текущего положения оси "на лету", во время ее движения? Не вбросить новое задание на выполнение (это совершенно другая задача "контурного режима"), а просто сказать, что в данный момент, вот это место — это позиция 3 200 851 или 0, или -600, или любое другое число.

Можно, хотя всё говорит об обратном. System Manager и XAE отказываются, сообщая: "Axis function is not allowed in motion!", — это означает, что функция недоступна во время движения.



Справочная система говорит, что для задания позиции "на лету" предназначен относительный режим (Relative), но ничего не говорит об абсолютном (Absolute) режиме. А ведь, на самом деле, всё работает, правда при условии, что вы делаете это из ПЛК-задачи и с помощью функционального блока MC_SetPosition.
Если есть вероятность что ваша программа будет работать на более ранних версиях TwinCAT, то лучше довериться System Manager и считать, что нельзя задавать позицию "на лету". Для большей уверенности стоит проверить, так как я проверял только на версиях 2.11.2254 и 3.1.4020.

Итак, сбросить позицию "на лету" в произвольное значение во время движения — можно. Рассогласование при этом не возникнет (хотя справочная неуверенно заявляет о возможности обратного). Что еще нужно знать о функции MC_SetPosition?

Существует два режима, передаваемые через параметр Mode. Абсолютный режим (Mode = FALSE) просто задает новое текущее значение позиции. Относительный же (Mode = TRUE) — задает смещение от текущего значения позиции. Например, если в относительном режиме задать отрицательное число — позиция уменьшится на заданное число, если положительное — увеличится.

В будущих версиях библиотеки (относительно версии 3.02.52 от 19.10.15) существует вероятность замены имени параметра Mode на Relative. Пока же это название остается прежним из соображения совместимости.

Когда-то давно, теперь уже в далеком 2005 году, функция MC_SetPosition называлась MC_SetActualPositionOnTheFly и ответ был сразу же понятен из ее названия.

January 24, 2017

Питание энкодерной оси

Нужно ли активировать питание энкодерной оси (Encoder Axis) с помощью функционального блока MC_Power?


Нет, не нужно. Достаточно просто регулярно читать статус переменной, связанной с осью движения. Следующего достаточно:

PROGRAM MAIN
VAR
    EncoderAxis : AXIS_REF;
END_VAR

(* Обновляем информацию об оси движения *)
EncoderAxis.ReadStatus;

(* Работаем с текущей позицией *)
IF EncoderAxis.NcToPlc.ActPos > 0 THEN
[...]
Стоит учитывать, что без вызова метода ReadStatus, автоматически обновляются только статусные поля структуры NcToPlc (поля, отвечающие за состояние оси). Поля, содержащие позицию, скорость и другое, обновляться без вызова ReadStatus не будут. Это также относится и к обычным (Continuous Axis) приводным осям.
Делаем предварительный вывод ― энкодерная ось отличается от обычной приводной (Continuous Axis) только тем, что преобразует параметры движения в цифру, но не осуществляет управление. Следовательно, силовое питание энкодерной оси не требуется.

― Хорошо, а что будет если все-таки задействовать MC_Power? Сможет ли он запретить вращение в обратную сторону или что-нибудь подобное?
― Нет, не сможет. Энкодерная ось всегда находится в неподвижном состоянии. Поля State.HasBeenStopped и .StandStill всегда равны TRUEState.MotionState также всегда равно MC_AXISSTATE_STANDSTILL. Теперь мы знаем, что MC_Power активирует и контролирует только управление движением (то есть выход), но никак не влияет на входные данные.

Что еще полезного в структуре State?

Поля .Moving / .NotMoving ― показывают, движется ли ось. Причем, ожидаемо, каламбур: .NotMoving = NOT .Moving. Направление движения помогают определить поля .NegativeDirection и .PositiveDirection.

Не ждите полезной информации от полей Error. Лучше следите за Status.IoDataInvalid. Это поле показывает валидность данных. Поле становится равным TRUE, когда данные неверны, что можно интерпретировать как ошибку энкодерной оси.

October 18, 2016

Я сделаю свой NC с рампами и траекториями

В частотных приводах AX5000 и сервомодулях EL72xx изначально заложена возможность прямого управления сервоусилителями: кидаете задание Velocity command value, формируете слово управления Master control word и постоянно следите за словом состояния Drive status word. По сути вам необходимо самостоятельно обрабатывать все, что есть в AT|MDT ветках сервоусилителя. Просто и дешево, но:
  • Не умеет масштабировать величины. Все значения задаются в инкрементах. Хотя можно реализовать пересчетные функции (как уже сделано в NC).
  • Только базовый набор функций: вкл/откл силового питания, вращение с заданной скоростью, абсолютное позиционирование, контроль тока, ограничение момента.
  • Все управление идет из ПЛК-задачи: если в программе тех. процесса допустить ошибку, то она отразится в том числе и на работе сервоусилителя, так как они все вместе работают внутри одной и той же задачи (в отличии от NC, которая работает как независимая подсистема TwinCAT).
  • Зависимость от времени цикла ПЛК-задачи. NC не зависит от времени цикла задачи, что положительно сказывается на скорости реакции, плавности/точности траекторий и пр. 
  • Нет разгонно-тормозных рамп, но можно реализовать их самостоятельно.
  • Зависимость от режима работы сервоусилителя: нельзя задать скорость вращения в режиме позиционирования и обратная ситуация — нельзя выйти в абсолютную позицию в режиме управления по скорости.
  • Нет ни гарантии, ни тех. поддержки: умер разработчик — умерла система.

Должны быть плюсы:
  • Дешево.
  • Будет работает на всем, что может обеспечить EtherCAT-мастер, в том числе и на контроллерах CX8010 + EK1110.


Что-то подобное уже всплывало в зачем нужен NC PTP и что он себе позволяет.

March 2, 2016

Конфигурирование AX2000-B900

Устаревшее оборудование выходит из строя, разработчик давно сгинул в лесах амазонки, а ЗИП внезапно требует первоначальной настройки. Источник адреса задается dip-переключателями #7-8.


1 2 3 4 5 6 7 8
------------------
0 0 0 0 0 0 0 1 – адрес выдается сервером (или роутером) через DHCP. Дипы #1..6 обязательно в OFF.
0 0 0 0 0 0 1 0 – адрес выдается BootP-сервером.
0 0 0 0 0 0 0 0 – адрес выдается RT-Ethernet мастером, т. е. контроллером.

Если адреса выдает RT-Ethernet-мастер и есть несколько подчиненных, то адреса выдаются последовательно, начиная с мастера, которому достается адрес 172.16.17.1, затем 172.16.17.2... 3... 4...

Также существует легенда, что дипами 1..6 можно непосредственно задать IP-адрес, но подтвердить это, пока не удалось.

December 30, 2015

Универсальная летающая пила

Кроме базовых возможностей управления движением (без интерполяций), TwinCAT NC PTP позволяет осуществлять более сложные виды управления движением. Одним из таких видов движения является «универсальная летающая пила» (Flying Saw).

В непрерывном производстве материалов «бесконечной длины» необходимо делить материал на куски заданной длины. Перед тем как процесс резки начнется, пила (нож, плазма, лазер, и т. п.) должны быть синхронизированы с конвейером и двигаться как единое целое в течение всего процесса отреза материала. По окончании отреза, пила должна вернуться на исходную позицию.

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

Минимальные требования:
  • ПЛК Бекхофф уровня TC40 и выше. Например: CX9020, P205NC, CX5020, CX2020.
  • TwinCAT 2 (NC PTP или NC I) или TwinCAT 3 (TC3 PLC/NC PTP 10, NC I).
  • Библиотека «NC Flying Saw». Заказные номера TS5055 (TwinCAT 2) или TF5055 (TwinCAT 3).

В какой-то момент библиотека была переписана и названа "Универсальной летающей пилой" (Universal Flying Saw), т. к. теперь обеспечивала поддержку разных видов пил (обычная летающая пила, диагональная летающая пила и др.).


Обычная летающая пила


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

Передаточное отношение между пилой и конвейером рассчитывается как обычная пропорция Vs / Vm. Если они равны, то получим передаточное отношение Vs / Vm = 1.



Диагональная летающая пила


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

В данном случае передаточное отношение рассчитывается чуть сложнее, т. к. диагональная скорость пилы складывается из скоростей движения по горизонтали и вертикали: Vs / [ cos(α) * Vm ].



Библиотека TcMC2_FlyingSaw.lib


  • Оси могут быть реальными, виртуальными (симуляция) или какими-либо другими внешними источниками актуальных данных.
  • Оси синхронизируются из любого состояния осей (стоп, движение вперед, назад, и т. п.).
  • Простая синхронизация по скорости.
  • Точная синхронизация по положению.
  • Скорость синхронизации может быть задана с учетом передаточного отношения.
  • Дополнительные опции позволяют задать реакцию на случай внезапного реверса движения конвейера.


В отличие от обычного электронного редуктора, доступного в NC PTP, сцепление и последующая синхронизация могут выполняться «на ходу»: когда скорости осей не равны нулю. Такая функция не доступна в электронном редукторе NC PTP.

Весь функционал библиотеки сосредоточен в двух функциональных блоках: MC_GearInVelo и MC_GearInPos. Первый просто синхронизирует оси по скорости. Второй синхронизирует оси ориентируясь на заданную позицию, т. е. только по достижении заданной позиции, оси будут синхронизированы. После этого, функциональный блок можно сбросить. Дальнейшее поддержание синхронности производится автоматически подсистемами NC и сервоусилителем.

Основной орган управления пилой – это позиция. Управляя позицией синхронизации, можно регулировать длину отреза материала (CUTTINGLENGTH).