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 можно перезаписать и заменить на другие, но свойства тормоза от этого не изменятся: параметры нужны только для автоматических расчетов внутри программы.

October 21, 2019

Linux + TwinCAT 3 + .Net Core 3 + ADS 5

Система реального времени по прежнему работает под Windows, но реализовать клиентскую сторону, визуализацию или массивную обработку данных (дата саенс, ага) под Linux уже можно.

Не то чтобы раньше нельзя было. Например, родные Бекхоффские реализации протокола ADS на C++, с неродным интерфейсом на QT. Python+Ads для обработки данных, например в блокнотах Jupiter и AdsClient (.NET Standart) для C# под гуем из WPF. Протокол открытый, почему бы и нет?

Теперь же Бекхофф выкатил в публичное превью библиотеки для работы с ADS под .NET Core 3. В первую очередь это означает кросс-платформенность для приложений на C# под Linux, Windows, Mac. О последнем я говорить не хочу, а для первых двух вырисовывается полный стек интересных технологий (или интересный стек полных технологий):
  • .NET Core 3.0
  • AvaloniaUI
  • Beckhoff.TwinCAT.Ads 5

Я еще раз подчеркну, сразу для двух операционных систем: Windows - Linux. Одно и то же приложение. Возможно необходимо пересобрать, тыкнув мышой в выбор операционки, но переписывать код уже не нужно. Выглядеть интерфейс будет одинаково на обеих операционках. Это благодаря Avalonia, которая почти как WPF.


TwinCAT.Ads 5.0.0-preview1


Итак, не далее как неделю назад, Бекхофф выложила превью библиотек. Нас ждут интриги, расследования и гонки на багги. "This is a prerelease version of Beckhoff.TwinCAT.Ads", — говорят нам RaHe, sveno, MichaelKn и Beckhoff со страниц NuGet. Далее идут инструкции как со всем этим жить, но это не точно. Потому что инструкции не работают. Как "нада жить" будет позже, а сейчас про состав выложенного:
  • TwinCAT.Ads 5.0.0-preview1
    Сборка для доступа к данным ПЛК через ADS. Совместима с предыдущими версиями библиотеки. Состав прежний: Client, Session, Read-Write Any Symbol, и тому подобное. Появились асинхронные операции. TcAdsClient переименован в AdsClient; AdsStream заменен на модные и современные Span+Memory.
  • Ads.AdsRouterConsole
    Под Linux нет рантайма и ADS-роутера соответственно. Поэтому Бекхофф предлагает нам нечто вроде выполняющее функции роутера. Запускается как консоль отдельно и самостоятельно, в том числе и под Linux.
  • Ads.TcpRouter
    А это уже не самостоятельная штука, зато можно засунуть себе в программу. Это как бы переносной роутер, который будет внутри вашей программы. Вокруг этой же штуки построена консоль AdsRouterConsole.
  • Ads.Reactive
    Тоже сборка для доступа к данным, но доступ "реактивным" способом.
  • AdsServerAbstractions
    Сервер и всё что сборки делят между собой. Про сервер как-нибудь в другой раз: где еще делать сервер как не под Linux?


Запускаем AdsRouterConsole


Сборка консоли роутера будет лежать в 
%USERPROFILE%\.nuget\packages\beckhoff.twincat.ads.adsrouterconsole\5.0.0-preview1\lib\netcoreapp3.0\TwinCAT.Ads.AdsRouterConsole.dll

...но(!) в инструкции, которая лежит в разделе Documentation NuGet, есть опечатка. На самом деле запускать нужно так:
dotnet TwinCAT.Ads.AdsRouterConsole.dll

...но(!) опять-таки  не запустится, так как этой сборке для запуска не хватает других сборок. Поэтому мы установим сборку TwinCAT.Ads.AdsRouterConsole в свой проект, и тогда .dll файл сборки будет лежать в папке /bin/Debug/netcoreapp3/, а в ней уже автоматом будут все необходимые для запуска консоли роутера сборки.

...но(!) при запуске мы получим следующую ошибку:
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in '...\bin\Debug\netcoreapp3\'.
Failed to run as a self-contained app. If this should be a framework-dependent app, add the ...\TwinCAT.Ads.AdsRouterConsole.runtimeconfig.json file specifying the appropriate framework.
Это связано с безопасностью в системе, поэтому возвращаемся к
%USERPROFILE%\.nuget\packages\beckhoff.twincat.ads.adsrouterconsole\5.0.0-preview1\lib\netcoreapp3.0
(да-да, именно для этого он нам и нужен был) и кладем файл TwinCAT.Ads.AdsRouterConsole.runtimeconfig.json рядом со сборкой консоли роутера, то есть в каталог /bin/Debug/netcoreapp3/ или /bin/Release/netcoreapp3/ проекта. Выбор конечного пути зависит от этапа разработки и конфигурации проекта.

Файл можно создать самостоятельно, вот его содержимое:

{
    "runtimeOptions": {
        "tfm": "netcoreapp3.0",
        "framework": {
            "name": "Microsoft.NETCore.App",
            "version": "3.0.0"
        }
    }
}

После этого, может запуститься, а может не запуститься и вылететь с ошибкой:
Error: An attempt was made to access a socket in a way forbidden by its access permissions.
...и это всё потому, что у вас уже запущен роутер. Приложение кросплатформенное, можно запускать как под Linux так и под Windows. Прибить работающий роутер можно остановив сервис TcSysSrv из командной строки PowerShell от имени Администратора или через Computer Management.


Таблица роутинга


На самом деле и сейчас не запустится: любому роутеру нужны настройки роутинга. Со стороны ПЛК придется настроить самостоятельно и вручную, а со стороны ПК сформировать XML файл StaticRoutes.xml, расположив его рядом со сборкой консоли роутера:

<?xml version="1.0" encoding="utf-8"?>
<TcConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="C:\TwinCAT3\Config\TcConfig.xsd">
  <Local>
      <Name>RALFH03</Name>
      <NetId>172.17.60.215.1.1</NetId>
  </Local>
  <RemoteConnections>
    <Route>
      <Name>CX-1CD661</Name>
      <Address>169.254.116.30</Address>
      <NetId>5.28.214.97.1.1</NetId>
      <Type>TCP_IP</Type>
    </Route>
  </RemoteConnections>
</TcConfig>

Секция Local — это имя и локальный Ams NetId адрес ПК. Выбираются произвольно, но в роутерах с обеих сторон, в записях касающихся ПК, этот адрес должен совпадать с обеих сторон, то есть во всех роутерах сразу. RemoteConnections — это про удаленную сторону, то есть о ПЛК. Сравним с настройками роутера на ПЛК.

Зайдем на ПЛК через web-конфигуратор: http://169.254.112.234/Config. Далее: TwinCAT → Connectivity → Add TwinCAT Route. Внизу списка жмем кнопки [+] и создаем запись роутинг для удаленного ПК (или ноутбука разработчика), удаленного теперь уже относительно ПЛК:

Route Name: RALFH03
AMS Net ID: 172.17.60.215.1.1
Transport Type: TCP/IP
Address: 169.254.7.118
Connection Timeout (ms): 3000

Сравните "тут" и "там" и станет немного понятнее.


Virtual Box


Я тестировал под виртуальной машиной на x64 Ubuntu 19.04. Для Virtual Box необходимо... краткое объяснение на пальцах — обязательно выставить все три сетевые параметра сетевого коннекта Убунты: IP адрес, маску и обязательно gateway (гейтвей можно произвольный, я выставлял 192.168.0.1). Не забыть установить исполняемому файлу атрибут исполняемого фалйа: chmod +x имя-исп-файла. Установить в системе dotnet core 3 (читайте справку Майкрософта).

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


Багги


А дальше начинаются скачки по дюнам и прочим неровностям превью бета версии библиотек. На любых функциях типа client.ReadSymbol("MAIN.Counter") я получал ошибку:
Stack overflow.
Aborted (core dumped)
...и приложение падает. Интересно, что точно такую же ошибку я получал когда пытался использовать независимую сборку независимого разработчика AdsClient. Видимо, корень проблемы одинаковый.

В то же время можно создать хэндл client.CreateVarHandle("MAIN.Counter"), а затем нормально работать на функциях чтения-записи через хэндлы. Также нормально работает чтение по имени переменной через реактивную подписку, которая к тому же неплохо ложится на реактивность Avalonia:

var valueObserver = Observer.Create(val => {
    Dispatcher.UIThread.InvokeAsync(() => {
        var mwvm = (MainWindowViewModel)DataContext;
        mwvm.Counter = val.ToString();
    });
});

IDisposable subscription =
    session.Connection
        .WhenNotification("MAIN.Counter", NotificationSettings.Default)
        .Subscribe(valueObserver);


То есть как-то работать уже можно и что-то рабочее уже вырисовывается:



Среда разработки


Теперь попробуем поработать под Linux — посмотрим в сторону среды разработки.

Как таковой среды еще нет, зато есть кроссплатформенный редактор Visual Studio Code, а к нему расширение vscode-st за авторством Сергея Романова. Расширение помогает работать с кодом на ST. Проект открытый, исходный код есть на GitHub. Самое главное, что проект не заброшен и развивается: я добавил туда пару новых штук, и внезапно разработчик принял пул-реквест, и так же мгновенно пересобрал расширение.


Подсветка синтаксиса, подсказка по переменным и ФБ, снипеты и прочие плюшки. Еще раз: это не отладчик и не среда разработки, а редактор кода, но это уже что-то. Остается дождаться чего-нибудь подобного TcXaeMgmt, ведь PowerShell Core уже работает под Linux, а роутероподобное ПО мы только что потрогали палочкой. Да что там, TcXaeMgmt уже можно установить, но работать командлеты не будут: отсутствует TwinCAT Automation Interface который построен на COM объектах.

Поэтому — ждем. Редактор файлов уже есть, остается прослойка для работы с загрузкой-выгрузкой файлов-проектов и пуск-стопом рантаймов, а там и до дебага недалеко (на самом деле, далеко).

October 14, 2019

Git и макросы TwinCAT 2 (CoDeSys)

У нас тут настолько TwinCAT 3.1, что некоторые молодые специалисты уже не видели второй версии. Что не отменяет сопровождение старых проектов и желание использовать контроль версий. К тому же есть родня в лице CoDeSys, где все также, но немного по другому.

TwinCAT 2 и Git плохо совместимы из-за бинарного формата проектов TwinCAT 2: использовать можно, но то же diff так просто не получится. Еще есть ENI (ENginering Interface), но оно стоит денег, хотя и не понятно почему? Вероятно, потому что нужен, но если что, есть бесплатное на python, но я не проверял. К тому же оно для Visual SourceSafe и SVN, а нужен Git.

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


Что такое, как и почему Git?


Читать можно в произвольном порядке.
  1. Understanding Git (как устроен и работает Git):
  2. Сходство и различие между Mercurial и Git. Ответ на вопрос: почему именно Git?
  3. Git: наглядная справка.
  4. Про Git. Книга и полное описание работы с Git.
  5. Git How To. Интерактивный тур.


Экспорт


Первое, что необходимо сделать, это избавиться от бинарного формата проекта. В PLC Control есть возможность работать из командной строки. Оттуда же можно экспортировать проект из единого бинарного .pro файла в набор текстовых .exp файлов.

Про командную строку и командные файлы PLC Control можно прочитать в Command Line/Command File Commands. Интересно, что экспортировать можно как в один текстовый файл (project export), так и в несколько (project expmul): тогда в каждом, отдельном файле будет лежать отдельный модуль проекта. Разделение модулей по нескольким файлам в дальнейшем облегчит контроль, сравнение и откат изменений в проекте.

Кроме непосредственно экспорта понадобится еще ряд команд, поэтому без командных файлов не обойтись. И это будут не только системные батники-cmd, но и макросы PLC Control.


Макросы


Другая возможность — написать для среды разработки небольшую библиотеку макросов, добавить ее в проект и запускать экспорт непосредственно из меню PLC Control.

Я буду хранить библиотеку макросов в файле Git.mac. Название выбрано не случайно, но об этом чуть позже. Содержимое .mac файла:

MACRO
MacroName: 'Git Commit'
MacroMenu: '&Commit'
MacroCmd: 'file save'
MacroCmd: 'query off ok'
MacroCmd: 'replace yesall'
MacroCmd: 'project expmul ~project-filename-pro'
MacroCmd: 'system git add *'
MacroCmd: 'system git commit -m "%date%-%time%"'
END_MACRO

Кратко, что здесь происходит:
  1. Сохраняем текущие изменения в файл проекта, делаем все по тихому и без вопросов: query off ok; replace yesall.
  2. Экспортируем с разбивкой модулей по отдельным файлам .exp в подкаталог project-filename-pro с помощью project expmul.
  3. Добавляем все изменения на git stage.
  4. Коммитим с автоматическим комментарием в виде текущих даты-времени.
Все просто. Из недостатков — коммиты не содержат внятных комментариев и необходимость вручную вписать вместо project-filename-pro имя файла проекта. Например, есть project-name.pro, в .mac файле будет записано как project expmul ~project-name, то есть просто отбрасываем расширение файла.
Перед экспериментами не забудьте создать репозиторий через git init.

Добавляем макрос в рабочий проект. Идем в Project → Option → Macros и добавляем библиотеку макросов Git.mac через кнопку Macrolibrary → Include...



После этого появится новый раздел меню Edit  Macros → Git  Commit. Несмотря на то, что макрос назван Git Commit, система взяла за основу имя файла библиотеки макросов, то есть просто выдернула его из имени файла Git.mac. Поэтому название файла библиотеки имеет значение.



.Gitignore


Немного приберемся в каталоге проекта. Файл git-игнора может содержать следующие расширения файлов: *.dfr, *.pro, *.bak, *.ci, *.wbp. Эти файлы бинарные, поэтому лучше чтобы их не было в репозитории Git.


Git commit


Я предпочитаю использовать командную строку вместо макросов, поэтому сделал себе .cmd файл который сканирует каталог проекта в поисках .pro файлов, а затем каждый из них экспортирует в свою собственную папку вида ~имя-pro-файла. После экспорта командный файл автоматически коммитит изменения в локальный репозиторий Git. Количество .pro файлов не ограничено.

Командный файл +commit.cmd:

@echo off
SETLOCAL
set TcPlcCtrl="C:\TwinCAT\Plc\TCatPlcCtrl.exe"

if exist "*.pro" (
    FOR %%i IN ("*.pro") DO (
        CALL :ExportProject %%~ni
    )
)

del %cmd%

git add *
git commit -m '%date%-%time%'

exit /b

:ExportProject

set ProjectName=%1

set ProjectPath=%ProjectName%.pro
set cmd=__project_export.tmp
set ExportTo=~%ProjectName%

echo replace yesall > %cmd%
echo query off ok >> %cmd%
echo file open %ProjectPath% >> %cmd%
echo project expmul %ExportTo% >> %cmd%
echo file close >> %cmd%
echo file quit >> %cmd%

%TcPlcCtrl% /show hide /cmd %cmd%

exit /b

ENDLOCAL


Восстановление проекта


Если вы вдруг решите откатить текущие изменения git checkout или перескочить на другую ветку git branch, то сначала необходимо выполнить требуемые команды Git и только затем сделать импорт .exp файлов.

Я опять-таки всё автоматизировал, но только импорт. Еще раз сначала придется выполнить команды Git, и только затем выполнять +restore.cmd:

@echo off
SETLOCAL
set TcPlcCtrl="C:\TwinCAT\Plc\TCatPlcCtrl.exe"

choice /c YN /T 30 /D N /M "Do you want to restore working dir up to the last commit [default = N]"
if %ERRORLEVEL% EQU 2 EXIT 1

if exist "*.pro" (
    FOR %%i IN ("*.pro") DO (
        CALL :RestoreProject %%~ni
    )
)

del %cmd%
exit /b

:RestoreProject

set ProjectName=%1

set cmd=__project_import.tmp
set ProjectPath=%ProjectName%.pro
set ImportFrom=~%ProjectName%

echo replace yesall > %cmd%
echo query off ok >> %cmd%
echo file open %ProjectPath% >> %cmd%
echo project import %ImportFrom%\*.* >> %cmd%
echo file save
echo file close >> %cmd%
echo file quit >> %cmd%

%TcPlcCtrl% /show hide /cmd %cmd%

exit /b

ENDLOCAL

October 10, 2019

Программная активация удаленного доступа

В новых ПЛК по умолчанию отключен удаленный доступ. Во имя безопасности, конечно же. И вот когда ты подключаешься удаленно через эр-ди-пи, ви-пи-эн и прочие тим-виверы, запускаешь CERHost, а на контроллере не активен Remote Display... На помощь приходит Beckhoff Device Manager.

Что делать, если не приходит?

Найти контроллер через System Manager, подключиться к ПЛК и залить в него хитрую программу, которая в свою очередь активирует удаленный доступ.


Автостарт через реестр


Реестре содержит раздел Launch90, в который можно записать имена программ для автостарта. Название ключа явно позаимствовано из Linux, но нам нужно активировать удаленный доступ, а за него на стороне ПЛК отвечает сервис CeRDisp.exe. Теперь всё готово, осталось подать материал в жерло FB_RegSetValue из TcUtilities.lib.

После добавления записи в реестр, необходимо перезагрузить ПЛК. Для этого воспользуемся функцией NT_Reboot из той же библиотеки. Результат:

PROGRAM MAIN
VAR
    Reboot: NT_Reboot;
    RegSetValue: FB_RegSetValue;

    newValue: STRING := 'CeRDisp.exe';
END_VAR
VAR CONSTANT
    HKLM_INIT_SUBKEY: STRING := 'init';
    REG_LAUNCH90_VALUE: STRING := 'Launch90';
END_VAR

(* @END_DECLARATION := '0' *)

RegSetValue(
    sNetId   := '',
    sSubKey  := HKLM_INIT_SUBKEY,
    sValName := REG_LAUNCH90_VALUE,
    eValType := REG_SZ,
    cbData   := LEN(newValue) + 1,
    pData    := ADR(newValue),
    bExecute := TRUE
);

IF NOT RegSetValue.bBUSY THEN
    Reboot( NETID := '', START := TRUE);
END_IF

END_PROGRAM


Что-то еще про автостарт приложений можно прочитать в Automatic start of CE applications. И автозапустить что-нибудь еще полезное.

October 9, 2019

TF1810. TwinCAT 3 PLC HMI Web

У Бекхоффа есть несколько видов визуализаций в которых иногда можно запутаться. Сейчас меня интересует веб-визуализация TF1810 устанавливаемая на ПЛК. Работает и запускается этот вид визуализаций непосредственно на ПЛК. Просмотр и управление тех. процессом производится оператором через браузер с удаленного компьютера.

Работает всё это через JavaScript и HTML5. На контроллере обычно уже установлен, настроен и работает IIS (Microsoft Internet Information Services). При подключении, клиенту отправляются данные только отображаемых на экране элементов. Данные отправляются (т. е. обновляются) циклически независимо от того изменились они или нет. Сам микро-веб сайт разворачивается на ПЛК в каталоге /TwinCAT/3.1/Boot/Plc/Port_851/Visu. Номер порта (Port_851) может быть другим, соответственно путь также немного изменится.

Клиент подключается и рабоатет через браузер: http://plc-name-or-ip-address/Tc3PlcHmiWeb/Port_851/Visu/webvisu.htm. Веб страница в браузере содержат два канваса (Canvas) на которых рисуется вся графика визуализации. Один канвас рисует фон (на случай статичного фона), другой канвас рисует активные элементы. Для отображения графики элементов используется векторный SVG.

В результате всё это работает достаточно быстро, даже при наличии нескольких клиентов. ПЛК нагружается только в рамках прокачки данных по сети через ADS. Графика и прочие визуальные контролы рисуется и нагружают только браузер клиента, никак не влияя на производительность ПЛК.


Visu Profile в 3.1.4024


Начиная с версии 3.1.4024 что-то кардинально поменялось в кухне проектов TwinCAT и теперь необходимо согласовывать версии визуализаций.
  1. Сначала запустить XAE без проекта.
  2. Выбрать необходимую версию TwinCAT.
  3. Загрузить проект над которым вы работаете.
  4. Выбрать в проекте Visu Profile "постарее".

Одновременно работать с разными версиями TwinCAT можно с помощью TwinCAT Remote Manager.