У цьому розділі пояснюються принципи реалізації компонентів 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. Потім спробуйте:

Копія екрана з детальною інформацією про виконання щойно створеного модуля HAL для передачі даних.
$ halrun

halcmd: loadusr passthrough

halcmd: show pin

    Компонентні контакти:
    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

    Компонентні контакти:
    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)», який змушує присвоювання виходу відбуватися не частіше ніж раз на секунду. Оскільки це компонент, що не працює в режимі реального часу, фактична затримка між присвоєннями може бути набагато довшою, якщо пам’ять, яка використовується компонентом passthrough, переноситься на диск, оскільки присвоєння може бути відкладено до тих пір, поки ця пам’ять не буде перенесена назад.

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

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. Константи

Використовуйте їх для уточнення деталей, а не значення, яке вони містять.

  • 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