У цьому розділі пояснюються принципи реалізації компонентів 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. Потім спробуйте:
$ 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)
Потім штифти створюються за допомогою викликів методів об’єкта компонента. Аргументами є: суфікс імені штифта, тип штифта та напрямок штифта. Для параметрів аргументами є: суфікс імені параметра, тип параметра та напрямок параметра.
Типи контактів та параметрів: |
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