1. Введение

Конфигурация переходит от теории к устройству — то есть к устройству HAL. Для тех, кто хоть немного разбирался в компьютерном программировании, этот раздел называется Hello World HAL.

halrun можно использовать для создания работающей системы. Это инструмент командной строки или текстового файла для настройки и настройки. Следующие примеры иллюстрируют его настройку и работу.

2. Halcmd

«halcmd» — это инструмент командной строки для управления HAL. Для halcmd существует более полная справочная страница, которая устанавливается вместе с LinuxCNC из исходного кода или из пакета. Если LinuxCNC был скомпилирован как run-in-place, страница руководства не устанавливается, но доступна в главном каталоге LinuxCNC с помощью следующей команды:

$ man -M docs/man halcmd

2.1. Обозначения

В этом руководстве команды для операционной системы обычно отображаются без приглашения оболочки UNIX, т. е. обычно со знаком доллара ($) или решеткой/двойным крестом (#). При прямом общении с HAL через halcmd or halrun подсказки показаны в примерах. Окно терминала находится в разделе Applications/Accessories в главной строке меню Ubuntu.

Пример команды в терминале - приглашения командной строки
me@computer:~linuxcnc$ halrun
(will be shown like the following line)
halrun

(the halcmd: prompt will be shown when running HAL)
halcmd: loadrt counter
halcmd: show pin

2.2. Табуляция-завершение

Ваша версия halcmd может включать в себя завершение табуляции. Вместо завершения имен файлов, как это делает оболочка, она дополняет команды идентификаторами HAL. Вам нужно будет ввести достаточно букв, чтобы получить уникальное совпадение. Попробуйте нажать Tab после запуска команды HAL:

Табуляция-завершение
halcmd: loa<TAB>
halcmd: load
halcmd: loadrt
halcmd: loadrt cou<TAB>
halcmd: loadrt counter

2.3. Среда RTAPI

RTAPI означает Real Time Application Programming Interface. Многие компоненты HAL работают в реальном времени, и все компоненты HAL хранят данные в общей памяти, поэтому компоненты реального времени могут получить к ним доступ. Обычный Linux не поддерживает программирование в реальном времени или тип общей памяти, необходимый HAL. К счастью, существуют операционные системы реального времени (RTOS), которые предоставляют необходимые расширения Linux. К сожалению, каждая RTOS действует по-своему.

Чтобы устранить эти различия, команда LinuxCNC разработала RTAPI, который обеспечивает согласованный способ взаимодействия программ с RTOS. Если вы программист, который хочет работать над внутренними компонентами LinuxCNC, возможно, вам захочется изучить linuxcnc/src/rtapi/rtapi.h, чтобы понять API. Но если вы обычный человек, все, что вам нужно знать о RTAPI, это то, что его (и RTOS) необходимо загрузить в память вашего компьютера, прежде чем вы что-либо сделаете с HAL.

3. Простой пример

3.1. Загрузка компонента

В этом руководстве мы будем предполагать, что вы успешно установили Live CD и, если используете RIP footnote: [Run In Place, когда исходные файлы загружены в пользовательский каталог, компилируются и выполняются непосредственно оттуда.], вызовите сценарий rip-environment, чтобы подготовить shell. В этом случае все, что вам нужно сделать, это загрузить в память необходимые модули RTOS и RTAPI. Просто запустите следующую команду из окна терминала:

Загрузка HAL
cd linuxcnc
halrun
halcmd:

Загрузив ОС реального времени и RTAPI, мы можем перейти к первому примеру. Обратите внимание, что приглашение теперь отображается как halcmd:. Это связано с тем, что последующие команды будут интерпретироваться как команды HAL, а не команды оболочки.

В первом примере мы будем использовать компонент HAL под названием siggen, который представляет собой простой генератор сигналов. Полное описание компонента siggen можно найти в разделе SigGen данного руководства. Это компонент реального времени. Чтобы загрузить компонент "siggen", используйте команду HAL loadrt.

Загрузка siggen
halcmd: loadrt siggen

3.2. Изучение HAL

Теперь, когда модуль загружен, пришло время представить halcmd — инструмент командной строки, используемый для настройки HAL. В этом руководстве будут представлены только некоторые функции halcmd. Для более полного описания попробуйте man halcmd или посмотрите ссылку в разделе HAL Commands этого документа. Первая функция halcmd — это команда show. Эта команда отображает информацию о текущем состоянии HAL. Чтобы отобразить все установленные компоненты:

Показать компоненты с помощью halrun/halcmd
halcmd: show comp

    Loaded HAL Components:
    ID     Type  Name                                PID   State
    3      RT    siggen                                    ready
    2      User  halcmd2177                          2177  ready

Поскольку halcmd сам по себе также является компонентом HAL, он всегда будет отображаться в списке. Число после "halcmd" в списке компонентов — это ID UNIX процесса. Можно запустить более одной копии halcmd одновременно (например, в разных окнах терминала), поэтому PID добавляется в конец имени, чтобы сделать его уникальным. В списке также показан компонент siggen, который мы установили на предыдущем шаге. RT в разделе Type указывает, что siggen — это компонент реального времени. User в разделе Type указывает, что это компонент, не работающий в реальном времени.

Далее, давайте посмотрим, какие контакты делает доступными siggen:

Показать контакты
halcmd: show pin

Component Pins:
Owner   Type   Dir        Value  Name
     3  float  IN             1  siggen.0.amplitude
     3  bit    OUT        FALSE  siggen.0.clock
     3  float  OUT            0  siggen.0.cosine
     3  float  IN             1  siggen.0.frequency
     3  float  IN             0  siggen.0.offset
     3  float  OUT            0  siggen.0.sawtooth
     3  float  OUT            0  siggen.0.sine
     3  float  OUT            0  siggen.0.square
     3  float  OUT            0  siggen.0.triangle

Эта команда отображает все контакты текущего HAL. Сложная система может иметь десятки или сотни контактов. Но сейчас контактов всего девять. Из этих контактов восемь являются плавающей запятой, а один — битовым (логическим). Шесть переносят данные из компонента siggen, а три используются для передачи настроек в компонент. Поскольку мы еще не выполнили код, содержащийся в компоненте, некоторые контакты имеют нулевое значение.

Следующий шаг — просмотр параметров:

Показать параметры
halcmd: show param

Parameters:
Owner   Type  Dir        Value   Name
     3  s32   RO             0   siggen.0.update.time
     3  s32   RW             0   siggen.0.update.tmax

Команда show param показывает все параметры в HAL. Сейчас каждый параметр имеет значение по умолчанию, которое ему было присвоено при загрузке компонента. Обратите внимание на столбец с надписью Dir. Параметры с пометкой -W доступны для записи и никогда не изменяются самим компонентом, вместо этого они предназначены для изменения пользователем, чтобы управлять компонентом. Мы увидим, как это сделать позже. Параметры, помеченные как R-, доступны только для чтения. Их можно изменить только компонентом. Наконец, параметр с надписью RW предназначен для чтения и записи. Это означает, что они изменяются компонентом, но также могут быть изменены пользователем. Примечание: параметры siggen.0.update.time и siggen.0.update.tmax предназначены для целей отладки и не будут рассматриваться в этом разделе.

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

Показать функции с помощью halcmd`
halcmd: show funct

Exported Functions:
Owner   CodeAddr  Arg       FP   Users  Name
00003   f801b000  fae820b8  YES      0  siggen.0.update

The siggen component exported a single function. It is not currently linked to any threads, so users is zero
[CodeAddr and Arg fields were used during development and should probably disappear.]
.

3.3. Запуск кода в реальном времени

Чтобы фактически запустить код, содержащийся в функции siggen.0.update, нам нужен поток реального времени. Компонент под названием threads, который используется для создания нового потока. Давайте создадим поток под названием "test-thread" с периодом 1 мс (1,000 мкс или 1,000,000 нс):

halcmd: loadrt threads name1=test-thread period1=1000000

Посмотрим, сработало ли это:

Показать потоки
halcmd: show thread

Realtime Threads:
     Period  FP     Name               (     Time, Max-Time )
     999855  YES    test-thread        (        0,        0 )

It did. The period is not exactly 1,000,000 ns because of hardware limitations, but we have a thread that runs at approximately the correct rate. The next step is to connect the function to the thread:

Добавить функцию
halcmd: addf siggen.0.update test-thread

До сих пор мы использовали halcmd только для просмотра HAL. Однако на этот раз мы использовали команду addf (добавить функцию), чтобы фактически изменить что-то в HAL. Мы сказали halcmd добавить функцию siggen.0.update в поток test-thread, и если мы еще раз посмотрим на список потоков, то увидим, что это удалось:

halcmd: show thread

Realtime Threads:
     Period  FP     Name                (     Time, Max-Time )
     999855  YES    test-thread         (        0,        0 )
                  1 siggen.0.update

Прежде чем компонент siggen начнет генерировать сигналы, необходим еще один шаг. При первом запуске HAL поток(и) фактически не выполняются. Это позволит вам полностью настроить систему до запуска кода реального времени. Как только вы будете довольны конфигурацией, вы можете запустить код реального времени следующим образом:

halcmd: start

Теперь генератор сигналов работает. Давайте посмотрим на его выходные контакты:

halcmd: show pin

Component Pins:
Owner   Type  Dir         Value  Name
     3  float IN              1  siggen.0.amplitude
     3  bit   OUT         FALSE  siggen.0.clock
     3  float OUT    -0.1640929  siggen.0.cosine
     3  float IN              1  siggen.0.frequency
     3  float IN              0  siggen.0.offset
     3  float OUT    -0.4475303  siggen.0.sawtooth
     3  float OUT     0.9864449  siggen.0.sine
     3  float OUT            -1  siggen.0.square
     3  float OUT    -0.1049393  siggen.0.triangle

И давайте посмотрим еще раз:

halcmd: show pin

Component Pins:
Owner   Type  Dir         Value  Name
     3  float IN              1  siggen.0.amplitude
     3  bit   OUT         FALSE  siggen.0.clock
     3  float OUT     0.0507619  siggen.0.cosine
     3  float IN              1  siggen.0.frequency
     3  float IN              0  siggen.0.offset
     3  float OUT     -0.516165  siggen.0.sawtooth
     3  float OUT     0.9987108  siggen.0.sine
     3  float OUT            -1  siggen.0.square
     3  float OUT    0.03232994  siggen.0.triangle

Мы быстро выполнили две команды show pin, и вы можете видеть, что выходные данные больше не равны нулю. Выходные сигналы синуса, косинуса, пилы и треугольника постоянно изменяются. Прямоугольный выход также работает, однако он просто переключается с +1,0 на -1,0 каждый цикл.

3.4. Изменение параметров

Настоящая сила HAL в том, что вы можете изменить ситуацию. Например, мы можем использовать команду setp для установки значения параметра. Давайте изменим амплитуду генератора сигналов с 1,0 на 5,0:

Настроить контакт
halcmd: setp siggen.0.amplitude 5
Проверьте параметры и контакты еще раз
halcmd: show param

Parameters:
Owner   Type  Dir         Value  Name
     3  s32   RO           1754  siggen.0.update.time
     3  s32   RW          16997  siggen.0.update.tmax

halcmd: show pin

Component Pins:
Owner   Type  Dir         Value  Name
     3  float IN              5  siggen.0.amplitude
     3  bit   OUT         FALSE  siggen.0.clock
     3  float OUT     0.8515425  siggen.0.cosine
     3  float IN              1  siggen.0.frequency
     3  float IN              0  siggen.0.offset
     3  float OUT      2.772382  siggen.0.sawtooth
     3  float OUT     -4.926954  siggen.0.sine
     3  float OUT             5  siggen.0.square
     3  float OUT      0.544764  siggen.0.triangle

Обратите внимание, что значение параметра siggen.0.amplitude изменилось на 5, и что выводы теперь имеют большие значения.

3.5. Сохранение конфигурации HAL

Большую часть того, что мы до сих пор делали с halcmd, было просто просмотром чего-либо с помощью команды show. Однако две команды фактически изменили ситуацию. По мере того, как мы проектируем более сложные системы с помощью HAL, мы будем использовать множество команд для настройки так, как мы хотим. HAL имеет память слона и сохранит эту конфигурацию, пока мы его не выключим. Но что насчет следующего раза? Мы не хотим вручную вводить кучу команд каждый раз, когда хотим использовать систему.

Сохранение конфигурации всего HAL одной командой.
halcmd: save

# components
loadrt threads name1=test-thread period1=1000000
loadrt siggen
# pin aliases
# signals
# nets
# parameter values
setp siggen.0.update.tmax 14687
# realtime thread/function links
addf siggen.0.update test-thread

Вывод команды save представляет собой последовательность команд HAL. Если вы начнете с empty HAL и запустите все эти команды, вы получите конфигурацию, которая существовала на момент выполнения команды save . Чтобы сохранить эти команды для дальнейшего использования, мы просто перенаправляем вывод в файл:

Сохраните конфигурацию в файл с помощью halcmd
halcmd: save all saved.hal

3.6. Выход из halrun

Когда вы закончите сеанс HAL, введите exit в командной строке halcmd:. Это вернет вас к системному приглашению и закроет сеанс HAL. Не закрывайте просто окно терминала, не завершив сеанс HAL.

Выход из HAL
halcmd: exit

3.7. Восстановление конфигурации HAL

Чтобы восстановить конфигурацию HAL, хранящуюся в файле "saved.hal", нам нужно выполнить все эти команды HAL. Для этого мы используем ключи "-f _<file name>_", который считывает команды из файла, и «-I» (заглавная буква i), который показывает приглашение halcmd после выполнения команд:

Запуск сохраненного файла
halrun -I -f saved.hal

Обратите внимание, что в файле saved.hal нет команды "start". Необходимо ввести ее снова (или отредактировать файл saved.hal, чтобы добавить ее туда).

3.8. Удаление HAL из памяти

Если произойдет неожиданное завершение сеанса HAL, возможно, вам придется выгрузить HAL перед началом следующего сеанса. Для этого введите следующую команду в окне терминала.

Удаление HAL
halrun -U

4. Stepgen Пример

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

Прежде чем мы сможем приступить к созданию этого нового примера, мы хотим начать с чистого листа. Если вы только что закончили один из предыдущих примеров, нам нужно удалить все компоненты и перезагрузить библиотеки RTAPI и HAL.

halcmd: exit

4.1. Установка компонентов

Теперь мы собираемся загрузить компонент генератора шаговых импульсов. Подробное описание этого компонента см. в разделе «Stepgen» Руководства интегратора. В этом примере мы будем использовать тип управления StepGen velocity. На данный момент мы можем пропустить детали и просто выполнить следующие команды.

В этом примере мы будем использовать тип управления velocity из компонента stepgen.

halrun
halcmd: loadrt stepgen step_type=0,0 ctrl_type=v,v
halcmd: loadrt siggen
halcmd: loadrt threads name1=fast period1=50000 name2=slow period2=1000000

The first command loads two step generators, both configured to generate stepping type 0. The second command loads our old friend siggen, and the third one creates two threads, a fast one with a period of 50 microseconds (µs) and a slow one with a period of 1 millisecond (ms).

Note
The fp1= parameter is deprecated and ignored. All threads now unconditionally support floating point.

Как и прежде, мы можем использовать halcmd show, чтобы просмотреть HAL. На этот раз у нас гораздо больше контактов и параметров, чем раньше:

halcmd: show pin

Component Pins:
Owner   Type  Dir         Value  Name
     4  float IN              1  siggen.0.amplitude
     4  bit   OUT         FALSE  siggen.0.clock
     4  float OUT             0  siggen.0.cosine
     4  float IN              1  siggen.0.frequency
     4  float IN              0  siggen.0.offset
     4  float OUT             0  siggen.0.sawtooth
     4  float OUT             0  siggen.0.sine
     4  float OUT             0  siggen.0.square
     4  float OUT             0  siggen.0.triangle
     3  s32   OUT             0  stepgen.0.counts
     3  bit   OUT         FALSE  stepgen.0.dir
     3  bit   IN          FALSE  stepgen.0.enable
     3  float OUT             0  stepgen.0.position-fb
     3  bit   OUT         FALSE  stepgen.0.step
     3  float IN              0  stepgen.0.velocity-cmd
     3  s32   OUT             0  stepgen.1.counts
     3  bit   OUT         FALSE  stepgen.1.dir
     3  bit   IN          FALSE  stepgen.1.enable
     3  float OUT             0  stepgen.1.position-fb
     3  bit   OUT         FALSE  stepgen.1.step
     3  float IN              0  stepgen.1.velocity-cmd

halcmd: show param

Parameters:
Owner   Type  Dir         Value  Name
     4  s32   RO              0  siggen.0.update.time
     4  s32   RW              0  siggen.0.update.tmax
     3  u32   RW     0x00000001  stepgen.0.dirhold
     3  u32   RW     0x00000001  stepgen.0.dirsetup
     3  float RO              0  stepgen.0.frequency
     3  float RW              0  stepgen.0.maxaccel
     3  float RW              0  stepgen.0.maxvel
     3  float RW              1  stepgen.0.position-scale
     3  s32   RO              0  stepgen.0.rawcounts
     3  u32   RW     0x00000001  stepgen.0.steplen
     3  u32   RW     0x00000001  stepgen.0.stepspace
     3  u32   RW     0x00000001  stepgen.1.dirhold
     3  u32   RW     0x00000001  stepgen.1.dirsetup
     3  float RO              0  stepgen.1.frequency
     3  float RW              0  stepgen.1.maxaccel
     3  float RW              0  stepgen.1.maxvel
     3  float RW              1  stepgen.1.position-scale
     3  s32   RO              0  stepgen.1.rawcounts
     3  u32   RW     0x00000001  stepgen.1.steplen
     3  u32   RW     0x00000001  stepgen.1.stepspace
     3  s32   RO              0  stepgen.capture-position.time
     3  s32   RW              0  stepgen.capture-position.tmax
     3  s32   RO              0  stepgen.make-pulses.time
     3  s32   RW              0  stepgen.make-pulses.tmax
     3  s32   RO              0  stepgen.update-freq.time
     3  s32   RW              0  stepgen.update-freq.tmax

4.2. Соединение контактов с сигналами

У нас есть два генератора шаговых импульсов и генератор сигналов. Теперь пришло время создать несколько сигналов HAL для соединения двух компонентов. Мы собираемся представить, что два генератора шаговых импульсов приводят в движение оси X и Y станка. Мы хотим перемещать стол по кругу. Для этого мы отправим косинусный сигнал на ось X, а синусоидальный сигнал на ось Y. Модуль siggen создает синус и косинус, но нам нужны «провода» для соединения модулей вместе. В HAL «провода» называются сигналами. Нам нужно создать два из них. Мы можем называть их как угодно, в этом примере это будут «X-vel» и «Y-vel». Сигнал «X-vel» предназначен для передачи от косинусного выхода генератора сигналов на вход скорости первого генератора шаговых импульсов. Первым шагом является подключение сигнала к выходу генератора сигналов. Чтобы подключить сигнал к выводу, мы используем команду net.

net command
halcmd: net X-vel <= siggen.0.cosine

Чтобы увидеть эффект от команды net, мы снова покажем сигналы.

halcmd: show sig

Signals:
Type          Value  Name     (linked to)
float             0  X-vel <== siggen.0.cosine

Когда сигнал подключен к одному или нескольким контактам, команда show выводит список контактов сразу после имени сигнала. Стрелка показывает направление потока данных — в данном случае данные передаются от контакта «siggen.0.cosine» к сигналу «X-vel». Теперь давайте подключим X-vel ко входу скорости генератора шаговых импульсов.

halcmd: net X-vel => stepgen.0.velocity-cmd

Мы также можем подключить сигнал оси Y Y-vel. Он предназначен для работы от синусоидального выхода генератора сигналов до входа второго генератора шаговых импульсов. Следующая команда в одной строке выполняет то, что две команды net выполнили для X-vel.

halcmd: net Y-vel siggen.0.sine => stepgen.1.velocity-cmd

Теперь давайте еще раз взглянем на сигналы и подключенные к ним контакты.

halcmd: show sig

Signals:
Type          Value  Name     (linked to)
float             0  X-vel <== siggen.0.cosine
                           ==> stepgen.0.velocity-cmd
float             0  Y-vel <== siggen.0.sine
                           ==> stepgen.1.velocity-cmd

Команда show sig поясняет, как именно данные проходят через HAL. Например, сигнал X-vel поступает с контакта siggen.0.cosine и идет на контакт stepgen.0.velocity-cmd.

4.3. Настройка выполнения в реальном времени — потоки и функции

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

halcmd: show funct

Exported Functions:
Owner   CodeAddr  Arg       FP   Users  Name
 00004  f9992000  fc731278  YES      0   siggen.0.update
 00003  f998b20f  fc7310b8  YES      0   stepgen.capture-position
 00003  f998b000  fc7310b8  NO       0   stepgen.make-pulses
 00003  f998b307  fc7310b8  YES      0   stepgen.update-freq

В общем, вам придется обратиться к документации каждого компонента, чтобы узнать, какие функции он выполняет. В этом случае функция siggen.0.update используется для обновления выходов генератора сигналов. Каждый раз, когда он выполняется, он вычисляет значения выходных сигналов синуса, косинуса, треугольника и прямоугольника. Чтобы сигналы были плавными, его необходимо запускать через определенные промежутки времени.

Остальные три функции относятся к генераторам шаговых импульсов.

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

The main function for the step pulse generator is stepgen.make_pulses. Every time make_pulses runs it decides if it is time to take a step, and if so sets the outputs accordingly. For smooth step pulses, it should run as frequently as possible. Because it needs to run so fast, make_pulses is highly optimized and performs only a few calculations.

Последняя функция, stepgen.update-freq, отвечает за масштабирование и некоторые другие вычисления, которые необходимо выполнять только при изменении команды частоты.

В нашем примере это означает, что мы хотим запускать siggen.0.update с умеренной скоростью для вычисления значений синуса и косинуса. Сразу после запуска siggen.0.update мы хотим запустить stepgen.update_freq, чтобы загрузить новые значения в генератор шаговых импульсов. Наконец, нам нужно запускать stepgen.make_pulses как можно быстрее для получения плавных импульсов. Поскольку мы не используем обратную связь по положению, нам вообще не нужно запускать stepgen.capture_position.

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

halcmd: show thread

Realtime Threads:
     Period  FP     Name               (     Time, Max-Time )
     996980  YES                  slow (        0,        0 )
      49849  YES                  fast (        0,        0 )

The two threads were created when we loaded threads. The first one, slow, runs every millisecond. We will use it for siggen.0.update and stepgen.update_freq. The second thread is fast, which runs every 50 microseconds (µs). We will use it for stepgen.make_pulses. To connect the functions to the proper thread, we use the addf command. We specify the function first, followed by the thread.

halcmd: addf siggen.0.update slow
halcmd: addf stepgen.update-freq slow
halcmd: addf stepgen.make-pulses fast

После того, как мы дадим эти команды, мы можем снова запустить команду show thread, чтобы увидеть, что произошло.

halcmd: show thread

Realtime Threads:
     Period  FP     Name               (     Time, Max-Time )
     996980  YES                  slow (        0,        0 )
                  1 siggen.0.update
                  2 stepgen.update-freq
      49849  NO                   fast (        0,        0 )
                  1 stepgen.make-pulses

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

4.4. Настройка параметров

Мы почти готовы запустить нашу систему HAL. Однако нам все еще нужно настроить несколько параметров. По умолчанию компонент siggen генерирует сигналы, которые колеблются от +1 до -1. Для нашего примера это нормально: мы хотим, чтобы скорость стола менялась от +1 до -1 дюйма в секунду. Однако масштабирование генератора шаговых импульсов не совсем правильное. По умолчанию он генерирует выходную частоту 1 импульс в секунду при входном значении 1,0. Вряд ли один импульс в секунду даст нам движение стола на один дюйм в секунду. Вместо этого предположим, что у нас есть ШВП со скоростью 5 оборотов на дюйм, соединенная с шаговым двигателем со скоростью 200 шагов на оборот и 10-кратным микрошагом. Таким образом, для одного оборота винта требуется 2000 шагов, а для перемещения на один дюйм — 5 оборотов. Это означает, что общее масштабирование составляет 10 000 шагов на дюйм. Нам нужно умножить входную скорость, подаваемую на генератор шаговых импульсов, на 10000, чтобы получить правильный выходной сигнал. Именно для этого нужен параметр stepgen.n.position-scale. В этом случае оси X и Y имеют одинаковое масштабирование, поэтому мы устанавливаем параметры масштабирования для обеих на 10000.

halcmd: setp stepgen.0.position-scale 10000
halcmd: setp stepgen.1.position-scale 10000
halcmd: setp stepgen.0.enable 1
halcmd: setp stepgen.1.enable 1

Это масштабирование скорости означает, что когда контакт stepgen.0.velocity-cmd равен 1,0, генератор шагов будет генерировать 10000 импульсов в секунду (10 кГц). При использовании двигателя и ШВП, описанных выше, ось будет перемещаться со скоростью ровно 1,0 дюйм в секунду. Это иллюстрирует ключевую концепцию HAL — такие операции, как масштабирование, выполняются на минимально возможном уровне, в данном случае в генераторе шаговых импульсов. Внутренний сигнал X-vel — это скорость стола в дюймах в секунду, а другие компоненты, такие как siggen, вообще не знают (или заботятся) о масштабировании. Если бы мы поменяли ШВП или двигатель, мы бы изменили только параметр масштабирования генератора шаговых импульсов.

4.5. Запустить его!

Теперь у нас все настроено и мы готовы к запуску. Как и в первом примере, мы используем команду start.

halcmd: start

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

5. Halmeter

Вы можете создавать очень сложные системы HAL, даже не используя графический интерфейс. Однако есть что-то приятное в том, чтобы видеть результат своей работы. Первый и самый простой инструмент с ГИП для HAL — это halmeter. Это очень простая программа, которая является HAL-эквивалентом удобного мультиметра (или аналогового измерителя для олдов).

Это позволяет наблюдать за контактами, сигналами или параметрами, отображая текущие значения этих объектов. Это очень простое в использовании приложение для графических сред. В консоли введите:

halmeter

Появятся два окна. Окно выбора самое большое и включает в себя три вкладки:

  • В одном перечислены все контакты, определенные в настоящее время в HAL,

  • в другом перечислены все сигналы,

  • в третьем перечислены все параметры.

Нажмите на вкладку, затем нажмите на один из элементов, чтобы выбрать его. В небольшом окне будет показано имя и значение выбранного элемента. Дисплей обновляется примерно 10 раз в секунду. Чтобы освободить место на экране, окно выбора можно закрыть кнопкой Close. В маленьком окне, скрытом под окном выбора при запуске программы, кнопка Select повторно открывает окно выбора, а кнопка Exit останавливает программу и закрывает оба окна.

Возможен запуск нескольких halmeter’ов одновременно, что дает возможность визуализировать несколько элементов одновременно. Чтобы открыть halmeter и высвободить консоль, запустив его в фоновом режиме, выполните следующую команду:

halmeter &

Можно запустить halmeter и заставить его сразу отображать элемент. Для этого добавьте аргументы pin|sig|par[am] name в командную строку. Он отобразит сигнал, контакт или параметр name, как только запустится. Если указанный элемент не существует, то он запустится нормально.

Наконец, если элемент указан для отображения, можно добавить -s перед pin|sig|param, чтобы указать halmeter использовать еще меньшее окно. Имя элемента будет отображаться в строке заголовка, а не под значением, и кнопки не будет. Это полезно для отображения большого количества halmeter’ов в небольшом пространстве.

Мы снова будем использовать компонент siggen, чтобы проверить halmeter. Если вы только что закончили предыдущий пример, то вы можете загрузить siggen, используя сохраненный файл. Если нет, мы можем загрузить его так же, как делали это раньше:

halrun
halcmd: loadrt siggen
halcmd: loadrt threads name1=test-thread period1=1000000
halcmd: addf siggen.0.update test-thread
halcmd: start
halcmd: setp siggen.0.amplitude 5

На данный момент у нас загружен и запущен компонент siggen. Пришло время запустить halmeter.

Запуск Halmeter
halcmd: loadusr halmeter

Первое окно, которое вы увидите, — это окно "Select Item to Probe".

Halmeter Окно выбора
Figure 1. Halmeter Окно выбора

Этот диалог имеет три вкладки. На первой вкладке отображаются все контакты HAL в системе. На втором отображаются все сигналы, а на третьем — все параметры. Мы хотели бы сначала посмотреть на контакт siggen.0.cosine, поэтому щелкните его, а затем нажмите кнопку "Close". Диалоговое окно выбора объекта для измерения закроется, и окно измерения будет выглядеть примерно так, как показано на следующем рисунке.

Halmeter Окно
Figure 2. Halmeter Окно

Чтобы изменить то, что отображает измеритель, нажмите кнопку "Select", которая возвращает окно "Select Item to Probe".

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

Чтобы выключить Halmeter, просто нажмите кнопку выхода.

Если вы хотите просмотреть более одного контакта, сигнала или параметра одновременно, вы можете просто запустить больше halmeter’ов. Окно halmeter было намеренно сделано очень маленьким, чтобы на экране могло быть одновременно много изображений.

6. Halshow

Сценарий halshow может помочь вам разобраться в работающем HAL. Он отображает выбранные значения HAL и постоянно их обновляет.

Это очень специализированная система, и она должна подключаться к работающему HAL. Он не может работать автономно, поскольку полагается на способность HAL "introspect" и сообщать то, что он знает о себе, через библиотеку интерфейса halcmd. Когда конфигурация LinuxCNC изменится, вывод halshow тоже будет другим.

Как мы вскоре увидим, способность HAL документировать себя является одним из ключей к созданию эффективной системы ЧПУ.

6.1. Starting Halshow

Halshow is available

  • in the AXIS menu under Machine/Show HAL Configuration,

  • in the TkLinuxCNC menu under Scripts/HAL Show,

  • in GMOCCAPY on the settings page.

halshow can also be started from a terminal command line and specify formats for integer and float items (pins or signals) and identify a saved watchlist file to use:

$ halshow --help
Usage:
  halshow [Options] [watchfile]
  Options:
           --help    (this help)
           --fformat format_string_for_float
           --iformat format_string_for_int
           --noprefs don't use preference file to save settings

Notes:
       Create watchfile in halshow using: 'File/Save Watch List'.
       LinuxCNC must be running for standalone usage.

Example to limit number of decimal points for floats and use a file named my.halshow in the current directory:

$ halshow  --fformat "%.5f" ./my.halshow

For more information regarding the format, please refer to the Tcl format man page.

Halshow Layout
Figure 3. Halshow Layout

At the left of its display as shown in above figure is a tree view, resembling what you may have seen as file browsers. At the right is a tabbed notebook with tabs for show, watch and settings.

6.2. HAL Tree Area

Filter Tree

Per default this entry filters the tree by pin names or tree-nodes by a regular expression. For example, entering "lim-sw" would filter the tree to the following:

Filtering tree for pin names with the substring "lim-sw".
joint.0.neg-lim-sw-in
joint.0.pos-lim-sw-in
joint.1.neg-lim-sw-in
joint.1.pos-lim-sw-in
joint.2.neg-lim-sw-in
joint.3.pos-lim-sw-in

If you would like to display all joint.0-related, you have to click the settings icon and select "Full path". Pay attention to escape the regex special characters, so you have to enter "joint\.1\." to explicitly request the dot and not also find joint 10.

Tree

The tree shows all of the major parts of a HAL. In front of each is a small plus (+) or minus (-) sign in a box to expand or collapse the corresponding section of the tree.

You can also expand or collapse the tree display using the Tree View menu at the upper left edge of the display.

Under Tree View you will find: Expand All, Collapse All; Expand Pins, Expand Parameters, Expand Signals; and Reload tree view. Reload tree view is useful when new components are loaded during runtime and should be displayed.

6.3. HAL Show Area

Halshow: Show Tab
Figure 4. Halshow: Show Tab

Clicking on the node name, "Components" in the tree for example, will show you (under the "Show" tab) all that HAL knows about the contents of that node. Figure Halshow Show Tab shows a list exactly like you will see if you click the "Components" name. The information display is exactly like those shown in traditional text based HAL analysis tools. The advantage here is that we have mouse click access, access that can be as broad or as focused as you need.

If we take a closer look at the tree display we can see that the six major parts of a HAL can all be expanded at least one level. As these levels are expanded you can get more focused with the reply when you click on the rightmost tree node. You will find that there are some HAL pins and parameters that show more than one reply. This is due to the nature of the search routines in halcmd itself. If you search one pin you may get two, like this:

Component Pins:
Owner  Type  Dir  Value  Name
06     bit    -W   TRUE  parport.0.pin-10-in
06     bit    -W  FALSE  parport.0.pin-10-in-not

The second pin’s name contains the complete name of the first.

New in 2.9

Selected text inside the Show tab can be copied by right-click or CTRL-C.
The Show area allows to add pins from selected text by using the right-click menu. All valid pins that are enclosed in the selection are added to the Watch tab.

6.4. Watch Tab Area

Clicking the watch tab produces a blank canvas. You can add signals and pins to this canvas and watch their values. You can add signals or pins when the watch tab is displayed by clicking on the name of it in the tree view.

New in 2.9

You can also add all sub-items of this node by selecting that in the right click menu (see figure Halshow Watch Tab).

The following figure shows this canvas with several pins.

Halshow Watch Tab
Figure 5. Halshow: Watch Tab

Watch displays bit type (binary) values using colored circles representing LEDs. They show as dark red when a bit signal or pin is false, and as light yellow whenever that signal is true. If you select a pin or signal that is not a bit type (binary) signal, watch will show it as a numerical value. Pins are displayed in black, signals in blue and parameters in brown.

Watch will quickly allow you to test switches or see the effect of changes that you make to LinuxCNC while using the graphical interface. Watch’s refresh rate is a bit slow to see stepper pulses, but you can use it for these if you move an axis very slowly or in very small increments of distance.

New in 2.9

The pins and signals that are writable have buttons for manipulation on the right side. Pins that are linked to a signal have disabled buttons. To set these values, the corresponding pin has to be unlinked from the signal. That can be done by right-click on the signal name and select "Unlink pin", see Watch Tach Context Menu.

The watch list will be saved automatically on exit. If you don’t want Halshow to save your watchlist, it can be disabled in the Settings.

Context Menu

New in 2.9

The context menu allows further:

  • Copy the pin name to clipboard

  • Set a value

  • Unlink a pin (if linked to a signal)

  • Show apin in the Tree view (highlights the pin, doesn’t scroll to the position)

  • Remove a pin from the list

Halshow: Watch Tab Context Menu
Figure 6. Halshow: Watch Tab Context Menu

6.5. Command Entry

In the lower part is an entry box to test HAL commands. The commands you enter here and the effect that they have on the running HAL are not saved. They will persist as long as LinuxCNC remains up but are gone as soon as LinuxCNC is.

New in 2.9

The command entry has a BASH-like history (during the session), so you can restore inserted commands with the arrow up key.

The entry box labeled "HAL Command:" will accept any of the commands listed for halcmd. These include:

  • loadrt, unloadrt (load/unload real-time module)

  • loadusr, unloadusr (load/unload non-realtime component)

  • addf, delf (add/delete a function to/from a real-time thread)

  • net (create a connection between two or more items)

  • setp (set parameter (or pin) to a value)

This little editor will enter a command any time you press enter or push the execute button. An error message from halcmd will be shown when these commands are not properly formed. If you are not certain how to set up a proper command, you’ll need to read again the documentation on halcmd and the specific modules that you are working with.

6.6. Settings

New in 2.9

The geometry of the window and the settings are saved in a file in the configuration directory on exit. If that path cannot be determined, they are stored in the home directory. The path will be displayed in the settings page. You can omit using the preferences file by calling halshow with the command line argument --no-prefs.
The further settings should be self-explaining.

Halshow Settings
Figure 7. Halshow Settings

6.7. Example/Tutorial

Let’s use this editor to add a differential module to a HAL and connect it to axis position so that we could see the rate of change in position, i.e., acceleration. We first need to load a HAL component named ddt, add it to the servo thread, then connect it to the position pin of a joint. Once that is done we can find the output of the differentiator in halscope. So let’s go.

loadrt ddt

Now look at the components node and you should see ddt in there someplace.

Loaded HAL Components:
ID Type        Name
10 User halcmd29800
09 User halcmd29374
08   RT         ddt
06   RT hal_parport
05   RT    scope_rt
04   RT     stepgen
03   RT      motmod
02 User   iocontrol

Sure enough, there it is. Notice that its ID is 08. Next we need to find out what functions are available with it so we look at functions:

Exported Functions:
Owner  CodeAddr      Arg  FP Users Name
  08   E0B97630 E0DC7674 YES     0 ddt.0
  03   E0DEF83C 00000000 YES     1 motion-command-handler
  03   E0DF0BF3 00000000 YES     1 motion-controller
  06   E0B541FE E0DC75B8  NO     1 parport.0.read
  06   E0B54270 E0DC75B8  NO     1 parport.0.write
  06   E0B54309 E0DC75B8  NO     0 parport.read-all
  06   E0B5433A E0DC75B8  NO     0 parport.write-all
  05   E0AD712D 00000000  NO     0 scope.sample
  04   E0B618C1 E0DC7448 YES     1 stepgen.capture-position
  04   E0B612F5 E0DC7448  NO     1 stepgen.make-pulses
  04   E0B614AD E0DC7448 YES     1 stepgen.update-freq

Here we look for owner #08 and see a function named ddt.0. We should be able to add ddt.0 to the servo thread and it will do its math each time the servo thread is updated. Once again we look up the addf command and find that it uses three arguments like this:

addf <functname> <threadname> [<position>]

We already know the functname=ddt.0 so let’s get the thread name right by expanding the thread node in the tree. Here we see two threads, servo-thread and base-thread. The position of ddt.0 in the thread is not critical. So we add the function ddt.0 to the servo-thread:

addf ddt.0 servo-thread

This is just for viewing, so we leave position blank and get the last position in the thread. The following figure shows the state of halshow after this command has been issued.

Addf command
Figure 8. Addf command

Next we need to connect ddt to something. But how do we know what pins are available? The answer is to look under pins. There we find ddt and see this:

Component Pins:
Owner Type  Dir Value       Name
08    float R-  0.00000e+00 ddt.0.in
08    float -W  0.00000e+00 ddt.0.out

That looks easy enough to understand, but what signal or pin do we want to to connect to it? It could be an axis pin, a stepgen pin, or a signal. We see this when we look at joint.0:

Component Pins:
Owner Type  Dir Value       Name
03    float -W  0.00000e+00 joint.0.motor-pos-cmd ==> Xpos-cmd

So it looks like Xpos-cmd should be a good signal to use. Back to the editor where we enter the following command:

linksp Xpos-cmd ddt.0.in

Now if we look at the Xpos-cmd signal using the tree node we’ll see what we’ve done:

Signals:
Type Value Name
float 0.00000e+00 Xpos-cmd
<== joint.0.motor-pos-cmd
==> ddt.0.in
==> stepgen.0.position-cmd

We see that this signal comes from joint.o.motor-pos-cmd and goes to both ddt.0.in and stepgen.0.position-cmd. By connecting our block to the signal we have avoided any complications with the normal flow of this motion command.

The HAL Show Area uses halcmd to discover what is happening in a running HAL. It gives you complete information about what it has discovered. It also updates as you issue commands from the little editor panel to modify that HAL. There are times when you want a different set of things displayed without all of the information available in this area. That is where the HAL Watch Area is of value.