В этом разделе объясняются принципы реализации компонентов HAL с помощью языка программирования Python.

1. Базовый пример использования

Компонент, не работающий в режиме реального времени, начинает с создания своих контактов и параметров, затем входит в цикл, который периодически управляет всеми выходами со входов. Следующий компонент копирует значение, отображаемое на его входном контакте (passthrough.in), на выходной контакт (passthrough.out) примерно раз в секунду.

#!/usr/bin/env python3
import hal, time
h = hal.component("passthrough")
h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)
h.newpin("out", hal.HAL_FLOAT, hal.HAL_OUT)
h.ready()
try:
    while 1:
        time.sleep(1)
        h['out'] = h['in']
except KeyboardInterrupt:
    raise SystemExit

Скопируйте приведенный выше листинг в файл с именем "passthrough", сделайте его исполняемым (chmod +x) и поместите в свой $PATH. Затем попробуйте его:

Копия экрана с подробной информацией о выполнении вновь созданного passthrough модуля HAL.
$ halrun

halcmd: loadusr passthrough

halcmd: show pin

    Component Pins:
    Owner Type  Dir     Value  Name
     03   float IN          0  passthrough.in
     03   float OUT         0  passthrough.out

halcmd: setp passthrough.in 3.14

halcmd: show pin

    Component Pins:
    Owner Type  Dir     Value  Name
     03   float IN       3.14  passthrough.in
     03   float OUT      3.14  passthrough.out

2. Компоненты и задержки, не относящиеся к реальному времени

Если вы быстро набрали "show pin", вы можете увидеть, что passthrough.out по-прежнему имеет старое значение 0. Это связано с вызовом time.sleep(1), который делает присвоение выходному контакту не чаще одного раза в секунду. Поскольку это компонент, не работающий в режиме реального времени, фактическая задержка между назначениями может быть намного дольше, если память, используемая транзитным компонентом, выгружается на диск, поскольку назначение может быть отложено до тех пор, пока эта память не будет выгружена обратно.

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

3. Создание контактов и параметров

h = hal.component("passthrough")

Сам компонент создается вызовом конструктора hal.component. Аргументами являются имя компонента HAL и (опционально) префикс, используемый для имен выводов и параметров. Если префикс не указан, используется имя компонента.

h.newpin("in", hal.HAL_FLOAT, hal.HAL_IN)

Затем выводы создаются путем вызова методов объекта компонента. Аргументами являются: суффикс имени контакта, тип контакта и направление контакта. Для параметров аргументами являются: суффикс имени параметра, тип параметра и направление параметра.

Table 1. Имена опций HAL

Типы контактов и параметров:

HAL_BIT

HAL_FLOAT

HAL_S32

HAL_U32

HAL_S64

HAL_U64

Направления контактов:

HAL_IN

HAL_OUT

HAL_IO

Направления параметров:

HAL_RO

HAL_RW

Полное имя контакта или параметра формируется путем объединения префикса и суффикса с помощью ".", поэтому в примере созданный вывод называется passthrough.in.

h.ready()

После создания всех выводов и параметров вызовите метод .ready().

3.1. Изменение префикса

Префикс можно изменить, вызвав метод .setprefix(). Текущий префикс можно получить, вызвав метод .getprefix().

4. Чтение и запись контактов и параметров

Для контактов и параметров, которые также являются правильными идентификаторами Python, значение можно получить или установить с помощью синтаксиса атрибута:

h.out = h.in

Для всех контактов, независимо от того, являются ли они правильными идентификаторами Python, значение можно получить или установить с помощью синтаксиса индексов:

h['out'] = h['in']

Чтобы увидеть все контакты с их значениями, getpins возвращает все значения в словаре этого компонента.

h.getpins()
>>>{'in': 0.0, 'out': 0.0}

4.1. Управляющие выходные контакты (HAL_OUT)

Периодически, обычно в ответ на таймер, все выводы HAL_OUT должны "управляться", присваивая им новое значение. Это следует делать независимо от того, отличается ли значение от последнего присвоенного значения. Когда контакт подключен к сигналу, его старое выходное значение не копируется в сигнал, поэтому правильное значение появится в сигнале только после того, как компонент присвоит новое значение.

4.2. Управление двунаправленными (HAL_IO) контактами

Вышеупомянутое правило не распространяется на двунаправленные контакты. Вместо этого двунаправленный контакт должен управляться компонентом только тогда, когда компонент желает изменить значение. Например, в интерфейсе стандартного энкодера, компонент энкодера только устанавливает для вывода index-enable значение FALSE (когда виден индексный импульс и старое значение TRUE), но никогда не устанавливает для него значение TRUE. Повторяющееся управление контактом FALSE может привести к тому, что другой подключенный компонент будет действовать так, как будто был замечен еще один индексный импульс.

5. Выход

Запрос halcmd unload для компонента доставляется как исключение KeyboardInterrupt. При поступлении запроса на выгрузку процесс должен либо завершиться через короткое время, либо вызвать метод .exit() компонента, если для завершения процесса завершения работы необходимо выполнить существенную работу (например, чтение или запись файлов).

6. Полезные функции

См. Интерфейс Python HAL для обзора доступных функций.

7. Constants

Используйте их для указания деталей, а не значения, которое они содержат.

  • HAL_BIT

  • HAL_FLOAT

  • HAL_S32

  • HAL_U32

  • HAL_S64

  • HAL_U64

  • HAL_IN

  • HAL_OUT

  • HAL_RO

  • HAL_RW

  • MSG_NONE

  • MSG_ALL

  • MSG_DBG

  • MSG_ERR

  • MSG_INFO

  • MSG_WARN

8. Системная информация

Прочтите их, чтобы получить информацию о системе реального времени.

  • is_kernelspace

  • is_rt

  • is_sim

  • is_userspace