1. Вступ

Panelui — це компонент, що не працює в режимі реального часу, для інтерфейсу кнопок до LinuxCNC або HAL:

  • Він декодує коди сканування ключів у стилі MESA 7I73 та викликає відповідну процедуру.

  • Він отримує вхідні дані від компонента реального часу — семплера. Семплер отримує вхідні дані або від компонента MESA 7I73, або від компонента sim_matrix_kb.

  • Panelui можна налаштувати за допомогою текстового файлу у стилі INI для визначення типів кнопок, типів контактів HAL та/або команд.

  • Його можна розширити за допомогою файлу-обробника на основі Python для додавання функцій.

Хоча фактичні кнопки введення повинні бути миттєвими, Panelui використовуватиме цей вхід для створення виводу перемикання, радіо або миттєвої кнопки.

2. Команди завантаження

Команда, що використовується для завантаження panelui (з необов’язковим параметром debug -d):

loadusr -W panelui -d

Це ініціалізує panelui, який шукатиме INI-файл panelui.ini в папці config або папці користувача.

Перевірити INI-файл можна за допомогою цієї команди:

loadusr pyui

Ця програма зчитає, спробує виправити, а потім збереже файл panelui.ini. Якщо будуть знайдені помилки, програма виведе їх у термінал.

У типовому HAL-файлі додаються такі команди:

# команди, необхідні для завантаження панелі
#
# семплер потрібен для panelui
# cfg= завжди має бути u для panelui. depth встановлює доступний буфер
loadrt sampler cfg=u depth=1025

#розкоментувати для перевірки INI-файлу panelui
#loadusr pyui

# -d = налагодження, -v = детальне налагодження
# -d покаже вам ідентифікацію натискання клавіш та викликані команди
# -v призначено для інформації розробника
loadusr -W panelui -d

# використання імітації кнопок замість плати MESA 7I73
# тому ми завантажуємо компонент sim_matrix_kb для перетворення контактів HAL у коди сканування клавіш
loadrt sim_matrix_kb

# з'єднати компоненти разом.
# семплер взаємодіє з panelui внутрішньо
net key-scan    sim-matrix-kb.0.out
net key-scan    sampler.0.pin.0

# додати компоненти panelui до потоку

addf sim-matrix-kb.0    servo-thread
addf sampler.0          servo-thread

3. Посилання на файл panelui.ini

Ключові слова
  • KEY= Використовується для позначення клавіші, на яку реагує кнопка. Це може бути NONE або номер ROW та номер стовпця, наприклад, R1C2. Рядок та стовпець можна використовувати лише один раз.

  • ВИХІД= Це встановлює тип виводу кнопки, наприклад, S32, U32, FLOAT, BIT, NONE, COMMAND, ZMQ.

  • ЗА ЗАМОВЧАННЯМ= Це встановлює початковий вихід групи або кнопки.

  • GROUP= У радіокнопках позначає групу, з якою взаємодіє кнопка.

  • GROUP_OUTPUT= встановлює вихідний сигнал групового контакту, якщо ця кнопка активна.

  • STATUS_PIN= Якщо значення TRUE (ІСТИНА), буде додано HAL-пін, який відображає поточний стан кнопки.

  • TRUE_STATE= встановлює вихідний сигнал на виводі HAL, якщо button має значення TRUE.

  • FALSE_STATE= встановлює ВИХІД, який матиме вивід HAL, якщо кнопка має значення FALSE.

  • TRUE_COMMAND= встановлює команду та аргументи, які будуть викликані, коли кнопка має значення TRUE.

  • FALSE_COMMAND= встановлює команду та аргументи, які будуть викликані, коли кнопка має значення FALSE.

  • TRUE_FUNCTION= встановлює функцію повідомлення ZMQ та аргументи, які будуть викликані, коли кнопка має значення TRUE.

  • FALSE_FUNCTION= встановлює функцію повідомлення ZMQ та аргументи, які будуть викликані, коли кнопка має значення FALSE.

Префікс HAL
[HAL_PREFIX]
    NAME= Yourname

Це дозволяє змінити префікс виводів HAL з «panelui» на довільну назву.

Налаштування повідомлень ZMQ
[ZMQ_SETUP]
  TOPIC = 'QTVCP'
  SOCKET = 'tcp://127.0.0.1:5690'
  ENABLE = True

Це налаштовує та активує обмін повідомленнями на основі ZMQ. TOPIC та SOCKET повинні відповідати програмі прослуховування.

Радіокнопки

Радіокнопки дозволяють активувати одночасно тільки одну кнопку в групі. Кожна група має власний вихідний контакт, окремий від кожної кнопки в групі. Визначення радіокнопок починаються з тексту «RADIO_BUTTON» в одинарних дужках.

[RADIO_BUTTONS]
  # Розділи з подвійними дужками визначають групи перемикачів.
  # Ім'я групи має бути унікальним і чутливим до регістру.
  # Вивід груп контролюється тим, яка кнопка активна, а не безпосередньо кодом клавіші.
  # DEFAULT посилається на кнопку в групі за іменем і чутливий до регістру.
  [[group1_name]]
    KEY = NONE
    OUTPUT = FLOAT
    DEFAULT = small
    # Розділи з потрійними дужками визначають кнопки в цій групі.
    # Імена кнопок повинні бути унікальними і чутливими до регістру.
    # У групі повинно бути принаймні дві кнопки.
    #
    # Ця кнопка, названа «small», керується клавішею рядка 0 стовпця 1.
    # При натисканні вона призведе до виведення групи .0001.
    # Вона не має власного виходу, але має стан
    # контакт, який буде слідувати за її поточним станом.
    # Оскільки ця кнопка знаходиться в групі, DEFAULT не має значення.
    # Оскільки OUTPUT не є «COMMAND», записи _COMMAND ігноруються.
    [[[small]]]
      KEY = R0C1
      GROUP = group1_name
      GROUP_OUTPUT = .0001
      OUTPUT = NONE
      STATUS_PIN = True
      TRUE_STATE = TRUE
      FALSE_STATE = FALSE
      TRUE_COMMAND = NONE, NONE
      FALSE_COMMAND = NONE, NONE
      DEFAULT = false
    # Ця кнопка, названа «large», керується клавішею рядка 0 стовпця 2.
    # При натисканні вона призведе до того, що вихід групи буде 1000.
    # Вона має власний вихід S32, який буде 20 при true і 0 при false.
    # Вона також має контакт стану, який буде слідувати за її поточним станом.
    # Оскільки ця кнопка знаходиться в групі, DEFAULT не має значення.
    # Оскільки OUTPUT не є «COMMAND», записи _COMMAND ігноруються.
    [[[large]]]
      KEY = R0C2
      GROUP = group1_name
      GROUP_OUTPUT = 1000
      OUTPUT = S32
      STATUS_PIN = True
      TRUE_STATE = 20
      TRUE_COMMAND = NONE, NONE
      FALSE_COMMAND = NONE, NONE
      FALSE_STATE = 0
      DEFAULT = false
Кнопки перемикання

Кнопки-перемикачі змінюють стан лише при кожному натисканні кнопки. Визначення кнопок-перемикачів починаються з тексту «TOGGLE_BUTTON» в одинарних дужках.

[TOGGLE_BUTTONS]
  # Кожна назва кнопки в подвійних дужках повинна бути унікальною і чутливою до регістру.
  # Ця кнопка, названа «tool_change», керується клавішею рядка 2 стовпця 5.
  # Вона має вихід BIT, який видає 1 у справжньому стані та 0 у хибному стані.
  # Вона також має контакт стану, який слідує за її поточним станом.
  # DEFAULT встановлює це значення як істинне при першій ініціалізації.
  # _COMMAND не використовується, оскільки OUTPUT не встановлено на COMMAND, але перевірка
  # додасть рядки незалежно від цього.
  [[tool_change]]
    KEY = R2C5
    OUTPUT = BIT
    TRUE_COMMAND = NONE, NONE
    FALSE_COMMAND = NONE, NONE
    STATUS_PIN = True
    DEFAULT = TRUE
    TRUE_STATE = 1
    FALSE_STATE = 0
Кнопки миттєвого натискання

Миттєві кнопки мають значення true при натисканні та false при відпусканні. Визначення миттєвих кнопок починаються з тексту MOMENTARY_BUTTON в одинарних дужках.

[MOMENTARY_BUTTONS]
  # Кожна назва кнопки в подвійних дужках повинна бути унікальною і чутливою до регістру.
  # Ця кнопка, названа «spindle_rev», керується клавішею рядка 2 стовпця 3.
  # Вона має вихід COMMAND, тому буде використовувати TRUE_COMMAND і FALSE_COMMAND.
  # Вона також має контакт стану, який буде слідувати за її поточним станом.
  # COMMANDs матиме ім'я команди, а потім будь-які необхідні аргументи.
  # Ця TRUE_COMMAND викликає внутрішню команду для запуску шпинделя в зворотному напрямку зі швидкістю 200 об/хв.
  # Якщо шпиндель вже запущений, швидкість обертання збільшиться.
  # DEFAULT не використовується з миттєвими кнопками.
  # _STATE не використовуються, оскільки OUTPUT встановлено на COMMAND, але перевірка
  # додасть рядки незалежно від цього.
  [[spindle_rev]]
    KEY = R2C3
    OUTPUT = COMMAND
    TRUE_COMMAND = SPINDLE_REVERSE_INCREASE, 200
    FALSE_COMMAND = None, NONE
    STATUS_PIN = True
    DEFAULT = FALSE
    TRUE_STATE = 1
    FALSE_STATE = 0

4. Довідник внутрішніх команд

Існує кілька внутрішніх команд, які ви можете використовувати.

home_selected
  • обов’язковий аргумент: номер осі (ціле число)

unhome_selected
  • обов’язковий аргумент: номер осі (ціле число)

spindle_forward_adjust
  • необов’язковий аргумент: початкове число RPM (ціле число) - за замовчуванням 100

  • Опис: Якщо шпиндель зупинено, він почне обертатися вперед. Якщо він вже працює, швидкість обертання збільшиться або зменшиться залежно від напрямку обертання шпинделя.

spindle_forward
  • необов’язковий аргумент: початкове число RPM (ціле число) - за замовчуванням 100

spindle_reverse
  • необов’язковий аргумент: початкове число RPM (ціле число) - за замовчуванням 100

spindle_reverse_adjust
  • необов’язковий аргумент: початкове число RPM (ціле число) - за замовчуванням 100

  • Опис: Якщо шпиндель зупинено, він почне обертатися у зворотному напрямку. Якщо він вже працює, швидкість обертання збільшиться або зменшиться залежно від напрямку обертання шпинделя.

spindle_faster
  • Опис: збільшує швидкість шпинделя на 100 об/хв

spindle_slower
  • Опис: зменшує швидкість шпинделя на 100 об/хв, доки об/хв не досягне 100

set_linear_jog_velocity
  • обов’язковий аргумент: швидкість у дюймах за хвилину (число з плаваючою комою)

  • опис: встановлює швидкість штовхання по осях 0,1,2,6,7,8 (X,Y,Z,U,V,W)

set_angular_jog_velocity
  • обов’язковий аргумент: швидкість у градусах за хвилину (число з плаваючою комою)

  • опис: встановлює швидкість штовхання на осях 3, 4, 5 (A.B.C)

continuous_jog
  • обов’язкові аргументи: номер осі (ціле число), напрямок (ціле число)

incremental_jog
  • обов’язкові аргументи: номер осі (ціле число), напрямок (ціле число), відстань (число з плаваючою комою)

quill_up
  • додаткові аргументи: абсолютне положення осі Z машини (число з плаваючою комою)

  • Опис: Перемістити вісь Z у задану позицію верстата

feed_hold
  • обов’язковий аргумент: стан (bool 0 або 1)

feed_override
  • обов’язковий аргумент: ставка (число з плаваючою комою)

rapid_override
  • обов’язковий аргумент: rate (float 0-1)

spindle_override
  • обов’язковий аргумент: ставка (число з плаваючою комою)

max_velocity
  • обов’язковий аргумент: ставка (число з плаваючою комою)

optional_stop
  • обов’язковий аргумент: стан (bool 0 або 1)

block_delete
  • обов’язковий аргумент: стан (bool 0 або 1)

single_block
  • обов’язковий аргумент: стан (bool 0 або 1)

smart_cycle_start
  • Опис: У режимі очікування запускає програму G-коду, якщо призупинено, виконується один рядок.

re_start line
  • обов’язковий аргумент: номер рядка (ціле число)

mdi_and_return
  • обов’язковий аргумент: команда(и) G-коду

  • Опис: записує поточний режим, викликає команди та повертається до цього режиму.

mdi
  • обов’язковий аргумент: команда(и) G-коду

  • Опис: встановлює режим MDI, викликає команди.

5. Повідомлення ZMQ

Panelui може надсилати повідомлення на основі ZMQ при натисканні кнопок.
Таким чином, panelui може взаємодіяти з іншими програмами, такими як екрани QtVCP.

[TOGGLE_BUTTONS]
  [[zmq_test]]
    KEY = R2C3
    OUTPUT = ZMQ
    TRUE_FUNCTION = ZMQ_BUTTON, 200
    FALSE_FUNCTION = ZMQ_BUTTON, 0
    STATUS_PIN = False
    DEFAULT = FALSE
    TRUE_STATE = 1
    FALSE_STATE = 0

Ось приклад програми, яка отримає повідомлення та виведе його на термінал.

import zmq
import json

# ZeroMQ Context
context = zmq.Context()

# Визначте сокет за допомогою "Контексту"
sock = context.socket(zmq.SUB)

# Визначте підписку та повідомлення з темою для прийняття.
topic = "" # всі теми
sock.setsockopt(zmq.SUBSCRIBE, topic)
sock.connect("tcp://127.0.0.1:5690")

поки True:
    topic, message = sock.recv_multipart()
    print('{} sent message:{}'.format(topic,json.loads(message)))

6. Розширення файлу обробника

Спеціальний файл можна використовувати для додавання власного коду Python, який буде доступний як команди. panelui_handler.py повинен бути написаний на Python і розміщений у папці конфігурації. Якщо panelui знайде там файл, він додасть його виклики функцій до доступних команд. Ось приклад файлу обробника, який додає дві функції — hello_world і cycle_mode:

# стандартний виклик обробника - це завжди буде обов'язковим
def get_handlers(linuxcnc_stat, linucnc_cmd, commands, master):
     return [HandlerClass(linuxcnc_stat, linucnc_cmd, commands, master)]

# Також обов'язковий - клас обробника класу HandlerClass:

    # Це буде досить стандартним для отримання доступу до всього.
    # linuxcnc_stat: це екземпляр стану Python для LinuxCNC.
    # linuxcnc_cmd: це екземпляр команди Python для LinuxCNC.
    # commands: це екземпляр команди, за допомогою якого можна викликати внутрішні процедури.
    # master: надає доступ до основних функцій/даних.

    def __init__(self, linuxcnc_stat, linuxcnc_cmd, commands, master):
        self.parent = commands
        self.current_mode = 0

    # Команди повинні мати такий вигляд:
    # def some_name(self, widget_instance, arguments from widget):
    # widget_instance надає доступ до функції/даних викликуючим віджетом.
    # arguments може бути списком аргументів, одним аргументом або None,
    # залежно від того, що було вказано в INI-файлі panelui.
    def hello_world(self, wname, m):
        # вивести на термінал, щоб ми знали, що все працює
        print('\nHello world\n')
        print(m)     # вивести аргумент(и)
        print(wname.metadata)    # вивести внутрішні метадані викликуючих віджетів (з файлу конфігурації)

        # Викликайте команду mdi для друку повідомлення в LinuxCNC.
        # Для цього потрібно, щоб LinuxCNC був встановлений, але це не перевіряється.
        # Батьківські команди очікують widget_instance - замінюється None.
        self.parent.mdi(None,'(MSG, Hello Linuxcnc World!)')

    # Кожен виклик цієї функції циклічно змінюватиме режим LinuxCNC.
    def cycle_mode(self, wname, m):
        if self.current_mode == 0:
            self.current_mode = 1
            self.parent.set_mdi_mode()
        elif self.current_mode == 1:
            self.current_mode = 2
            self.parent.set_auto_mode()
        else:
            self.current_mode = 0
            self.parent.set_manual_mode()
        print(self.current_mode)

    # Код котла, часто потрібен
    def __getitem__(self, item):
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)