October 29, 2018

Введение PowerShell для TwinCAT

В TwinCAT 3 есть штуки, позволяющие автоматизировать рутинные последовательности действий. Дальше как в известной байке с реддита: "Этично ли будет не сообщать работодателю, что я автоматизировал свою работу"?

В текущем проекте мне необходимо периодически перегружать TwinCAT: остановить сервис TwinCAT, запустить сервис TwinCAT, перевести локальный рантайм в режим конфигурации или в рабочий режим. Вообще, не проблема написать все это на C#, но здесь уместнее будет использовать командную строку и какой-нибудь скриптовый язык программирования. Под Linux есть bash и Python. Под Windows они тоже есть, но это противоестественно для его экосистемы. Поэтому будем экологичны — воспользуемся PowerShell 'ом.

PowerShell строится вокруг инфраструктуры .NET как и C#. Он также имеет удобный доступ к COM-объектам, а на них построены множество сервисов TwinCAT. Дальше хвалить не буду, начнем чистую практику. В идеале, я хочу получить кнопку, которая будет перезапускать TwinCAT в один клик. См. иллюстрацию справа →

Перезагрузить TwinCAT несложно — достаточно остановить и стартовать заново системный сервис TcSysSrv. Сделать это можно вручную или через командную строку. Сначала, стоп: net stop TcSysSrv; затем, рестарт — net start TcSysSrv, но после этого TwinCAT запустится в режиме стоп (красная иконка). Чтобы перевести его в какой‑либо рабочий или полурабочий конфигурационный режим, необходимо использовать функции ADS.API. К сожалению, через командную строку они не доступны: нужно запускать System Manager или XAE.


Инсталляция


Запустить консоль PowerShell можно из меню Пуск: клавиша  с окошком Windows → открывается меню Пуск, начинаете набирать powershe... Там же можно запустить встроенный в Windows редактор PowerShell ISE. При запуске от имени администратора, появляется больше возможностей, но и больше дыр в защите вашего ПК.


Чтобы перезапустить сервис TwinCAT можно использовать команду Restart-Service TcSysSrv -Force. Ключ -Force избавит от лишних вопросов. Причем, заметьте, не просто остановить или запустить, а одной командой остановить и перезапустить. Уже удобнее, чем было, но есть одно "но"(!) — перед запуском необходимо разобраться с правами на запуск командлетов-скриптов PowerShell: Get-ExecutionPolicy и Set-ExecutionPolicy. Погуглите по русски или читайте справочную систему на английском-немецком Check the Powershell Cmdlet Execution policy, это домашнее задание.

Теперь осталось разобраться с функциями ADS.API. Для них есть NuGet-PowerShell пакет TcXaeMgmt. Перед использованием, его необходимо установить командой Install-Module -Name TcXaeMgmt, соглашаясь [Y] со всем, что предложат:


Windows PowerShell
(C) Корпорация Майкрософт (Microsoft Corporation). Все права защищены.

PS C:\Windows\system32> Install-Module -Name TcXaeMgmt

Для продолжения требуется поставщик NuGet
Для взаимодействия с репозиториями на основе NuGet модулю PowerShellGet требуется версия поставщика NuGet "2.8.5.201"
или более новая. Поставщик NuGet должен быть доступен в "C:\Program Files (x86)\PackageManagement\ProviderAssemblies"
или "C:\Users\username\AppData\Local\PackageManagement\ProviderAssemblies". Поставщик NuGet можно также установить,
выполнив команду "Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force". Вы хотите, чтобы модуль
PowerShellGet установил и импортировал поставщик NuGet прямо сейчас?
[Y] Да - Y  [N] Нет - N  [S] Приостановить - S  [?] Справка (значением по умолчанию является "Y"):Y

Ненадежный репозиторий
Идет установка модулей из ненадежного репозитория. Если вы доверяете этому репозиторию, измените его значение
InstallationPolicy, запустив командлет Set-PSRepository. Вы действительно хотите установить модули из "PSGallery"?
[Y] Да - Y  [A] Да для всех - A  [N] Нет - N  [L] Нет для всех - L  [S] Приостановить - S  [?] Справка
(значением по умолчанию является "N"):Y
PS C:\Windows\system32>



Командлет


Для переключения режимов работы TwinCAT из PowerShell, используется команда: Set-AdsState -State Config.

Вообще, после установки пакета TcXaeMgmt, вы сможете делать из командой строки практически всё что угодно:... конкретнее, читайте в about_TcXaeMgmt.help.txt. Только помните — так как вы будете влиять на системные сервисы и другие важные штуки Windows, от вас часто будут требовать права Администратора. Их тоже можно выдавать автоматически из скрипта PowerShell.

Итоговый командлет, большую часть которого составляет выделение админских прав, выгляди так:

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).
        IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 
{
    Start-Process
        -WindowStyle Hidden
        -Verb RunAs
        powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"";
    exit
}

Restart-Service TcSysSrv -Force
Set-AdsState -State Config -Force


Сохраняем скрипт в файл с расширением .ps1. Файл кладем в C:\TwinCAT\3.1\Target\StartMenuAdmin. Здесь же делаем на него ссылку-ярлык и изменяем имя ярлыка на удобное нам название. Оно тут же появится в системном меню TwinCAT, картинка которого была в начале поста.


October 8, 2018

Сторожевой пес для CX8090

Сторожевой таймер (или watchdog, или вотчдог для краткости в дальнейшем) нужен в критических ситуациях. В щите сбора данных — может быть, а вот в станке, я ставлю его необходимость под сомнение. Тем не менее, вопросы типа "боюсь, что программа зависнет" или более самоуверенные — "что, если зависнет контроллер", задают постоянно. В CX8090 такая функция есть.

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

Все испытания проводились на новом ПЛК CX8090, произведенном 2 августа 2018 года.

История библиотеки


Я беру с полки CD-диск c официальным дистрибутивом TwinCAT 2 за 2013 год и открываю исходный код библиотеки TcSystemCX80xx.lib, предназначенной специально для CX80xx. Функции вотчдога в ней еще нет.

Диск за 2014 год — функции все еще нет. Версия библиотеки 1.0.2. Да собственно чего тянуть, функция была добавлена только в версии 1.0.3, но на диск попасть не успела или просто тестировалась какое-то время. Вот комментарий разработчика:

2014/02/17 | 1.0.3 | V2.11.0 (Build 2239) | ICH | adding F_CX80xxSetWatchdog


Мне, к сожалению, не удалось найти старые библиотеки на сайте Бекхофф, хотя я бы с удовольствием покопался в истории промышленного софтостроения. Так что, конкретно указать на версию TwinCAT я не могу. Начиная с версии TwinCAT 2.11 (build 2249) внезапно появляется версия 1.0.6, которая до сих пор лежит на сайте Бекхофф. И это не самая последняя версия, так как с последними дистрибутивами TwinCAT 2 распространяется версия библиотеки 1.0.7.

За все это время функциональный блок вотчдога не изменялся ни разу.


Как спустить сторожевого пса


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

FUNCTION F_CX80xxSetWatchdog : BYTE
VAR_INPUT
    tTimeOut : TIME; (* Watchdog TimeOut Time *)
    bEnable  : BOOL; (* Enable / Disable Watchdog *)
END_VAR

Это функция. Она не требует инстанциирования как функциональный блок. Просто регулярно вызывайте ее с (bEnable = TRUE), когда нужна функция сторожа; или вызовите блок единственный раз с (bEnable = FALSE), если нужно отключить таймер. Другими словами, блок требует регулярного вызова каждый цикл или по крайней мере не реже, чем это задано в параметре tTimeOut.
По идее функции должны быть сосредоточены сами в себе и ни коим образом не влиять на глобальное окружение. В данном же случае, такое применение уместно, так как: (а) функция всегда существует в единственном экземпляре и всегда требует ввода двух обязательных параметров; (б) другие программные единицы TwinCAT 2 так не умеют. В TwinCAT 3 мы могли бы попробовать шаблон Singleton.
На входе функции всего два параметра: (1) время реакции tTimeOut типа TIME, который может принимать значения в диапазоне от 500 миллисекунд (не меньше) до 127 секунд (не больше); (2) и параметр активациия/деактивации таймера bEnable типа BOOL. Куда уж проще.

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

...и через заданное время tTimeOut — ПЛК перезагрузится.

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

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

После того как функция отработает, мы получаем на выходе битовую маску типа BYTE, а по сути всего лишь три значимых бита:

(* return enable state *)
nRetVal.0           := bEnabled;
nRetVal.1           := bMinWDTimeAct;
nRetVal.2           := bMaxWDTimeAct;
F_CX80xxSetWatchdog := nRetVal;

Далее номера битов в байте выхода:
  • бит 0 — установлен, когда таймер запущен.
  • бит 1 — установлен, когда время таймаута меньше или равно 500 миллисекундам.
  • бит 2 — установлен, когда время таймаута больше или равно 127 секунд 500 мс.


Что внутри будильника?


Заглянем в недра тундры. Вотчдог хранит время таймаута в 500 миллисекундных интервалах. 127 секунд и 500 миллисекунд или 127 500 — это как раз 255 раз по 500. Затем это значение сдвигается на восемь бит "влево" в старший байт, а в младшем байте выставляются биты разрешения или запрещения.

Выбор таких временных интервалов в 500 мс возможно связан с "медленным" и неточным таймером вотчдога в архитектуре ARM9, который непосредственно встроен в железо. Медленный он в целях энергосбережения и потому что работает сам по себе, обходится без "точных кварцев" и других дорогостоящих электронных компонентов. Это очень топорное и упрощенное объяснение, но его вполне достаточно для текущего уровня поста.

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

Интересно, что вотчдог отключается не каким-то там специальным битом (его установкой или сбросом), а установкой максимально возможного значения временного интервала = 127с 500мс. Именно это происходит, когда мы вызываем функцию со сброшенным флагом разрешения (bEnable = FALSE).


Практика


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

PROGRAM MAIN
VAR
    state, cnt : INT;
    z : int := -1;
END_VAR

(*[...]*)

F_CX80xxSetWatchdog(tTimeOut := T#3s, bEnable := TRUE);

CASE state OF
0:
    F_CX8090_LED_WD(eMode := eLED_RED_OFF);
    F_CX8090_LED_ERR(eMode := eLED_RED_OFF);

    z := z + 1;
    state := 10;
    
10: (* breakpoint *)
    ;
    
20: (* zero division *)
    z := state / z;
    
30: (* inf. loop *)
    F_CX8090_LED_WD(eMode := eLED_RED_FLASHING_200ms);
    WHILE TRUE DO
        ;
    END_WHILE
    F_CX8090_LED_WD(eMode := eLED_RED_OFF);
END_CASE

cnt := cnt + 1;


Помигаем светодиодом на прощанье


На корпусе CX8090 есть индикатор WD (=Watchdog), который в документации заявлен как не используемый в прошивке для CX8080 / CX809x. Тем не менее у нас есть механизм для управления этими лампами: функция F_CX8090_LED_WD управляет светодиодом WD, F_CX8090_LED_ERR — управляет светодиодом ERR (для ошибок). Доступны несколько режимов свечения и мигания с различной скважностью: покопайтесь в типах данных библиотеки.

Касательно отключения индикаторов, то оба индикатора двухцветные. Поэтому не важно какой цвет индикатора выключать: красный (eLED_RED_OFF) или зеленый (eLED_GREEN_OFF), отключается сразу весь светодиод, то есть оба цвета свечения пропадают одновременно.

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

F_CX8090_LED_WD(eMode := eLED_RED_FLASHING_200ms);

WHILE itHaveToContinueThen DO
    ; (* что-то делаем в цикле *)
END_WHILE

F_CX8090_LED_WD(eMode := eLED_RED_OFF);


И еще раз, постарайтесь не использовать сторожевой таймер.

October 4, 2018

Веб-конфигуратор для CX8090

Последнее время Бекхофф встраивает в свои контроллеры веб-интерфейс для начальной настройки ПЛК. Это хорошо, потому что через ADS-роутер можно кое-как выяснить IP и AmsNetId -адреса ПЛК, но для запуска FTP-сервера или сервиса удаленного доступа — этого уже мало. В умный по сути коплер CX8090 просто некуда воткнуть святую троицу монитор-клавиатура-мышь. Разъемы для них не предусмотрены и не поддерживаются. Надо изгаляться... надо было, так как теперь все это делается через веб-интерфейс. По крайней мере первый шаг, который, как известно, чего-то-там для человечества.

Находим контроллер через TC2 System Manager или роутер TwinCAT 3: иконка TC3 в системном лотке (traybar) → Router → Edit Routes → TwinCAT Static Routes. В колонке Address видим IP-адресс ПЛК. Открываем любимый браузер. Для разнообразия, и чтобы показать, что никакой разницы нет, я взял нелюбимый в народе Edge.

Вводим в адресную строку: IP-адресс-ПЛК/config. Логин по умолчанию: webguest, пароль: 1.



Есть на что посмотреть и с чем поработать. И сразу же, чтобы не забыть потом, включаем удаленный доступ для работы с ПЛК через CERHost. А дальше уже не проблема запустить FTP-сервер, "залить" русские шрифты и поправить настройки в реестре Windows CE.