Как на самом деле запускается текущая конфигурация TwinCAT 3?
Все ниже перечисленные действия можно и нужно делать через официальный
Automation Interface, а пока соберем пачку файлов из загрузочного каталога
C:\TwinCAT\3.1\Boot\ и сравним
их между собой с помощью бесплатной
WinMerge.
Нам нужно больше файлов. Будем последовательно вносить изменения в текущую
конфигурацию, активировать ее, а затем копировать из
каталога Boot только интересные файлы.
... и сравнивать их между собой. Может быть и не так много файлов, как я
собрал.
CurrentConfig.tszip
Это обычный zip-архив. Хранит копию проекта .tsproj для текущей
конфигурации. Например, TwinCAT Project1.tsproj. Здесь хранятся
значения параметров предусмотренные конфигурацией изначально. На самом деле
при старте системы загружаются не они, а значения, хранящиеся в файле
CurrentConfig.xml.
CurrentConfig.xml
Файл состоит из ряда xml-секций. Часть секций содержит параметры текущей
конфигурации:
- TcBootProject — корень. Содержит дату активации конфигурации CreateTime.
- System — системные настройки: сколько выделить памяти, за каким ядром закрепить, размер стека, ...
- Drivers — какие подсистемы TwinCAT 3 загрузить при старте: IO, NC, RTime, ... Аналогично тому, что я писал про загрузку системного модуля NC PTP.
- InitCmds — команды при старте системы
- PostCmds — команды после старта системы
- ProjectInfo — описание текущего проекта конфигурации: уникальный идентификатор {GUID}, путь к файлу проекта, типы данных, ...
Offline → Online
Для примера я буду использовать параметры энкодера NC-оси. Это удобно, так
как я только что изменял
параметры NC оси
официальным путем через функции типа MC_WriteParameter, но у меня
остался открытым вопрос, как работает
MC_WriteParameterPersistent.
После ряда экспериментов в текстовом редакторе, выяснилось, что содержимое
.tsproj файла проекта содержит параметры по умолчанию. Эти параметры
можно ассоциировать с графой Offline Value в таблицах параметров
энкодера. Если изменить эти параметры в файле проекта, а затем перезапустить
TwinCAT (Run → Config → Run), то текущее значение параметров в графе
Online Value не изменится. Получается, что эти изменения никак
не влияют на параметры работающего в данный момент проекта.
После небольшой проверки стало понятно, что при активации проекта эти данные
транслируются и сохраняются в CurrentConfig.xml. Параметры этого
xml-файла как раз и являются Online данными. Если их
изменить, а затем перезапустить TwinCAT (Run → Config → Run), то мы применим
новые значения к работающему проекту. Именно эти параметры применяются при
загрузке текущего проекта и старте TwinCAT 3. Возможно, что TwinCAT 2 ведет
себя аналогично.
InitCmds
Эта xml-секция содержит список команд или операций отправляющих значения
параметров в сервис или устройство. Например, для NC один из множества
параметров - это настройки энкодера. Параметры записываются пачками, в виде
большого (или не очень) бинарного пакета.
- key — описание операции.
- port — ADS-порт устройства или сервиса.
- iGrp — индекс группы параметра.
- iOffs — индекс смещения параметра.
- data — бинарный пакет байтов, содержащий данные для параметров. В шестнадцатеричных кодах, то есть два символа на байт. Данные пишутся в память, поэтому какие-либо границы параметров не указываются. Бинарный массив просто накладывается на пул адресов.
- message — сообщение для лога TwinCAT.
Внедряемся в конфиг
Сравнив файлы, я нашел, что для задания параметров энкодера необходимо
обращаться к ADS-сервису
Port: 500; iGrp: 5124; iOffs: 0. ADS порт 500 отвечает за системный сервис NC (см.
AmsPort Enumeration). Секция data начинается с номера оси `01`, затем идут
какие-то неинтересные в данный момент данные, и с позиции 96 длинною в 16
символов идет значение Scaling Factor Numerator. Шестнадцать символов
— это hex-представление 8 байт данных, что хорошо укладывается в тип данных
LREAL/double.
Теперь задача заключается в следующем: найти секцию InitCmd у
которой есть потомки с port = 500, iGrp = 5124 и
ключ data начинающийся символами `01`. Затем преобразовать
новое значение параметра в hex-вид и перезаписать его значение в ключ
data. По окончании сохранить XML, перезапустить TwinCAT и
наслаждаться результатом изменившегося параметра в графе
Online Value.
Код можно смотреть и редактировать на гитхабе:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Xml.Linq; | |
namespace Tc3_CurrentConfig | |
{ | |
public class CurrentConfig | |
{ | |
const string CURRENTCONFIG_PATH = @"C:\TwinCAT\3.1\Boot\CurrentConfig.xml"; | |
/// <summary> | |
/// Writes Scaling Factor Numerator | |
/// </summary> | |
/// <param name="newValue">New value of Scaling Factor Numerator</param> | |
/// <param name="axisNo">NC axis number. Count begins from 1. 1 is a first axis.</param> | |
/// <returns>Current value of Scaling Factor Numerator</returns> | |
public static double WriteScalingFactorNumerator(double newValue, int axisNo) | |
{ | |
if (axisNo < 1 || axisNo > 255) | |
throw new ArgumentOutOfRangeException( "axisNo", axisNo, | |
"1 >= axisNo <= 255. Count begins from 1. 1 is a first axis."); | |
const int HEX_START_INDEX = 96; | |
const int HEX_VALUE_LENGTH = 16; // double = 8 bytes length | |
string hexAxisNo = axisNo.ToString("X2"); | |
/// Loading /////////////////////////////////////////////////////// | |
XDocument doc = XDocument.Load(CURRENTCONFIG_PATH); | |
var xEncAxis1 = doc.Descendants() | |
.Single(e => | |
e.Name.LocalName == "InitCmd" | |
&& e.Elements().Where( | |
ee => (ee.Name.LocalName == "port" && ee.Value == "500" ) | |
|| (ee.Name.LocalName == "iGrp" && ee.Value == "5124") | |
|| (ee.Name.LocalName == "iOffs" && ee.Value == "0" ) | |
|| (ee.Name.LocalName == "data" && ee.Value.StartsWith(hexAxisNo)) ) | |
.Count() == 4 ); | |
var xData = xEncAxis1.Elements().Single(e => e.Name.LocalName == "data"); | |
string data = xData.Value; | |
/// Current Value ///////////////////////////////////////////////// | |
string hexValue = data.Substring(HEX_START_INDEX, HEX_VALUE_LENGTH); | |
double currentDoubleValue = BitConverter.ToDouble(HexToByteArray(hexValue)); | |
/// Write New Value /////////////////////////////////////////////// | |
hexValue = BitConverter.ToString(BitConverter.GetBytes(newValue)) | |
.Replace("-","") // BitConverter returns like this AA-BB-CC-... | |
.ToLower(); // Tc3 writes hex in lower case | |
xData.Value = data.Substring(0, HEX_START_INDEX) + hexValue + data.Substring(HEX_START_INDEX + HEX_VALUE_LENGTH); | |
doc.Save(CURRENTCONFIG_PATH); | |
return currentDoubleValue; | |
} | |
// inefficient but fun, see: https://stackoverflow.com/a/321404 | |
public static byte[] HexToByteArray(string hexValue) | |
{ | |
return Enumerable.Range(0, hexValue.Length / 2) | |
.Select(x => Convert.ToByte(hexValue.Substring(x * 2, 2), 16)) | |
.ToArray(); | |
} | |
} | |
} |
MC_WriteParameterPersistent
Используя тестовую программу из статьи про
параметры NC осей, я параллельно сохранял файлы из загрузочного каталога Boot. Так я
смог быстро отследить, что именно происходит и каким-таким образом параметры
переживают перезагрузку.
И снова CurrentConfig.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<InitCmd runtimeadded="true"> | |
<key>Init34\NC: ChangeParameter 400100010023</key> | |
<port>500</port> | |
<iGrp>16385</iGrp> | |
<iOffs>65571</iOffs> | |
<data>011764cbf275493f</data> | |
<message>Initialization of boot parameter failed (MC_WriteParameterPersistent)</message> | |
</InitCmd> |
Система создает специальную запись в конце
файла CurrentConfig.xml. Посмотрите, как она отметила эту запись
специальным атрибутом
runtimeadded="true". Теперь
понятно, как такие параметры переживают перезагрузку.
Номер порта 500 остался без изменения, а вот группа-смещение изменились, да
и содержимое секции data похудело, выродившись в конкретное значение
параметра (16 символов → 8 байт → LREAL/double тип).
Если обратиться к документации
TwinCAT 3 ADS Interface NC
в инфосисе, обнаружится, что наконец-то используются официально
задокументированные штуки. Смотреть в п.2.4.1 "Index offset" specification
for axis parameter (Index group 0x4000 + AxisID).
iGrp: 16385 = 0x00004001 (0x4000 + AxisID)
iOffs: 65571 = 0x00010023 (0x00n10023. Component of the scaling factor:
numerator)
Всё, секрет раскрыт.
No comments
Post a Comment
Note: Only a member of this blog may post a comment.