1. Цільова аудиторія
Цей документ є збіркою нотаток про внутрішню структуру LinuxCNC. Він в першу чергу цікавий розробникам, проте значна частина інформації, що міститься в ньому, може бути цікавою також системним інтеграторам та іншим особам, які просто цікавляться тим, як працює LinuxCNC. Значна частина цієї інформації на сьогодні є застарілою і ніколи не перевірялася на точність.
2. Організація
Буде розділ для кожного з основних компонентів LinuxCNC, а також розділ (розділи), що описують, як вони працюють разом. Цей документ знаходиться в стадії розробки, і його структура може змінитися в майбутньому.
3. Терміни та визначення
-
«AXIS» (ОС) — Ось є одним із дев’яти ступенів свободи, що визначають положення інструменту в тривимірному декартовому просторі. Ці дев’ять осей позначаються як X, Y, Z, A, B, C, U, V і W. Лінійні ортогональні координати X, Y і Z визначають положення кінчика інструменту. Кутові координати A, B і C визначають орієнтацію інструменту. Другий набір лінійних ортогональних координат U, V і W дозволяє інструменту рухатися (зазвичай для різання) відносно попередньо зміщених і обернутих осей. На жаль, термін «вісь» іноді також використовується для позначення ступеня свободи самої машини, наприклад, сідла, столу або пінолі фрезерного верстата типу Bridgeport. На верстаті Bridgeport це не викликає плутанини, оскільки рух столу безпосередньо відповідає руху вздовж осі X. Однак плечові та ліктьові суглоби руки робота та лінійні приводи гексапода не відповідають руху вздовж будь-якої декартової осі, і загалом важливо розрізняти декартові осі та ступені свободи машини. У цьому документі останні будуть називатися «суглобами», а не осями. Графічні інтерфейси користувача та деякі інші частини коду не завжди дотримуються цього розрізнення, але внутрішні компоненти контролера руху дотримуються його.
-
«JOINT» — склін є однією з рухомих частин машини. Скліни відрізняються від осей, хоча ці два терміни іноді (помилково) використовуються для позначення одного й того самого поняття. У LinuxCNC склін є фізичним об’єктом, який можна переміщати, а не координатою в просторі. Наприклад, піноль, коліно, сідло та стіл фрезерного верстата Bridgeport є склінами. Плече, лікоть і зап’ястя руки робота є суглобами, як і лінійні приводи гексапода. Кожен суглоб має пов’язаний з ним двигун або привід певного типу. Суглоби не обов’язково відповідають осям X, Y і Z, хоча для машин з тривіальною кінематикою це може бути так. Навіть на цих машинах положення суглоба і положення осі є принципово різними речами. У цьому документі терміни «суглоб» і «вісь» використовуються обережно, щоб відобразити їх чітке значення. На жаль, це не завжди так. Зокрема, графічні інтерфейси для машин з тривіальною кінематикою можуть приховувати або повністю ігнорувати різницю між суглобами і осями. Крім того, у файлі INI термін «вісь» використовується для даних, які точніше було б описати як дані суглоба, такі як масштабування вхідних і вихідних даних тощо.
|
Note
|
Це розрізнення було введено у версії 2.8 LinuxCNC. Файл INI отримав новий розділ [JOINT_<num>]. Багато параметрів, які раніше належали до розділу [AXIS_<letter>], тепер знаходяться в новому розділі. Інші розділи, такі як [KINS], також отримали нові параметри, щоб відповідати цьому. Було надано скрипт оновлення для перетворення старих INI-файлів у нову конфігурацію осей/з’єднань. |
-
«POSE» — Поза — це повністю визначене положення в 3D-декартовому просторі. У контролері руху LinuxCNC під позою ми маємо на увазі структуру EmcPose, що містить шість лінійних координат (X, Y, Z, U, V і W) та три кутові (A, B і C).
-
«coord», або скоординований режим, означає, що всі шарніри синхронізовані і рухаються разом відповідно до вказівок коду вищого рівня. Це звичайний режим під час обробки. У скоординованому режимі команди, як правило, подаються в декартовій системі координат, і якщо верстат не є декартовим, команди перетворюються кінематикою для переміщення кожного шарніра в необхідне положення.
-
«Вільний» означає, що команди інтерпретуються в просторі суглобів. Він використовується для ручного переміщення (поштовхування) окремих суглобів, хоча це не заважає переміщати кілька суглобів одночасно (я так думаю). Повернення в вихідне положення також здійснюється у вільному режимі; фактично, машини з нетривіальною кінематикою повинні бути повернуті в вихідне положення, перш ніж вони зможуть перейти в режим координації або телеоперації.
-
«teleop» — це режим, який вам, ймовірно, знадобиться, якщо ви бігаєте з гексаподом. Команди бігу, реалізовані контролером руху, є спільними бігами, які працюють у вільному режимі. Але якщо ви хочете перемістити гексапод або подібну машину, зокрема, вздовж декартової осі, ви повинні керувати більш ніж одним суглобом. Саме для цього і призначений «teleop».
4. Огляд архітектури
Архітектура LinuxCNC складається з чотирьох компонентів: контролер руху (EMCMOT), контролер дискретних входів-виходів (EMCIO), координатор завдань (EMCTASK) та кілька текстових і графічних інтерфейсів користувача. Кожен з них буде описаний у цьому документі як з точки зору проектування, так і з точки зору розробників (де знайти необхідні дані, як легко розширити/змінити щось тощо).
4.1. Архітектура програмного забезпечення LinuxCNC
На найзагальнішому рівні LinuxCNC є ієрархією трьох контролерів: обробника команд рівня завдань та інтерпретатора програм, контролера руху та дискретного контролера вводу-виводу. Дискретний контролер вводу-виводу реалізований як ієрархія контролерів, в даному випадку для підсистем шпинделя, охолодження та допоміжних (наприклад, estop). Контролер завдань координує дії контролерів руху та дискретного вводу-виводу. Їхні дії програмуються у звичайних програмах числового управління «G та M код», які інтерпретуються контролером завдань у повідомлення NML та надсилаються до руху.
5. Вступ до контролера руху
Контролер руху є компонентом, що працює в режимі реального часу. Він отримує команди управління рухом від компонентів LinuxCNC, що не працюють в режимі реального часу (тобто інтерпретатора G-коду/завдання, графічних інтерфейсів користувача тощо) і виконує ці команди в режимі реального часу. Комунікація з контексту, що не працює в режимі реального часу, до контексту, що працює в режимі реального часу, відбувається за допомогою механізму передачі повідомлень IPC із використанням спільної пам’яті та за допомогою шару абстракції апаратного забезпечення (HAL).
Стан контролера руху стає доступним для решти LinuxCNC через той самий IPC спільної пам’яті для передачі повідомлень та через HAL.
Контролер руху взаємодіє з контролерами двигунів та іншим обладнанням реального та нереального часу за допомогою HAL.
Цей документ передбачає, що читач має базові знання про HAL, і використовує такі терміни, як «контакти HAL», «сигнали HAL» тощо, не пояснюючи їх. Більш детальну інформацію про HAL можна знайти в посібнику HAL. В іншому розділі цього документа ми розглянемо внутрішню структуру HAL, але в цьому розділі ми використовуємо лише API HAL, визначений у src/hal/hal.h.
5.1. Модулі контролера руху
Функції контролера руху в режимі реального часу реалізовані за допомогою модулів реального часу — спільних об’єктів простору користувача для систем Preempt-RT або модулів ядра для деяких реалізацій режиму реального часу в режимі ядра, таких як RTAI:
-
tpmod - планування траєкторії
-
homemod - функції самонаведення
-
motmod - обробляє команди NML та керує обладнанням через HAL
-
«кінематичний модуль» — виконує прямі (суглоби-->координати) та зворотні (координати->суглоби) кінематичні розрахунки
LinuxCNC запускається за допомогою скрипта linuxcnc, який зчитує файл конфігурації INI і запускає всі необхідні процеси. Для управління рухом в реальному часі скрипт спочатку завантажує модулі tpmod і homemod за замовчуванням, а потім завантажує модулі кінематики і руху відповідно до налаштувань у файлах halfiles, зазначених у файлі INI.
Замість стандартних модулів можна використовувати власні (створені користувачем) модулі повернення до вихідної позиції або планування траєкторії за допомогою налаштувань файлу INI або опцій командного рядка. Власні модулі повинні реалізовувати всі функції, що використовуються стандартними модулями. Для створення власного модуля можна використовувати утиліту halcompile.
6. Блок-схеми та потік даних
Наступний рисунок є блок-схемою спільного контролера. На кожне з’єднання припадає один спільний контролер. Спільні контролери працюють на рівні, нижчому за кінематику, на якому всі з’єднання є повністю незалежними. Усі дані для з’єднання містяться в єдиній структурі з’єднання. Деякі елементи цієї структури видно на блок-схемі, наприклад coarse_pos, pos_cmd та motor_pos_fb.
На рисунку вище показано п’ять із семи наборів інформації про положення, які формують основний потік даних через контролер руху. Сім форм даних про положення є такими:
-
emcmotStatus->carte_pos_cmd - Це бажане положення в декартових координатах. Воно оновлюється зі швидкістю траєкторії, а не сервоприводу. У режимі координат воно визначається планувальником траєкторії. У режимі teleop вона визначається планувальником траєкторії? У вільному режимі вона або копіюється з actualPos, або генерується шляхом застосування прямих кінематичних рівнянь до (2) або (3).
-
emcmotStatus->joints[n].coarse_pos - Це бажане положення в координатах з’єднання, але до інтерполяції. Воно оновлюється зі швидкістю траєкторії, а не сервоприводу. У режимі координат вона генерується шляхом застосування обернених кінів до (1) У режимі телеоператора вона генерується шляхом застосування обернених кінів до (1) У вільному режимі вона копіюється з (3), як я думаю.
-
'emcmotStatus->joints[n].pos_cmd - Це бажане положення, в координатах суглоба, після інтерполяції. Новий набір цих координат генерується кожний сервоперіод. У режимі координат він генерується з (2) інтерполятором. У режимі телеоператора він генерується з (2) інтерполятором. У вільному режимі він генерується планувальником траєкторії вільного режиму.
-
emcmotStatus->joints[n].motor_pos_cmd - Це бажане положення в координатах двигуна. Координати двигуна генеруються шляхом додавання компенсації люфту, компенсації похибки ходового гвинта та зміщення (для повернення в початкове положення) до (3). Воно генерується однаково незалежно від режиму і є виходом до контуру PID або іншого контуру положення.
-
emcmotStatus->joints[n].motor_pos_fb - Це фактичне положення в координатах двигуна. Це вхідні дані від енкодерів або інших пристроїв зворотного зв’язку (або від віртуальних енкодерів на машинах з відкритим контуром). Воно «генерується» шляхом зчитування даних з пристрою зворотного зв’язку.
-
emcmotStatus->joints[n].pos_fb - Це фактичне положення в координатах з’єднання. Воно генерується шляхом віднімання зміщення, компенсації похибки ходового гвинта та компенсації люфту від (5). Воно генерується однаково незалежно від режиму роботи.
-
emcmotStatus->carte_pos_fb - Це фактичне положення в декартових координатах. Воно оновлюється зі швидкістю траєкторії, а не сервоприводу. В ідеалі, фактичне положення завжди обчислюється шляхом застосування прямої кінематики до (6). Однак пряма кінематика може бути недоступною або непридатною для використання, оскільки одна або кілька осей не повернуті в початкове положення. У цьому випадку є такі варіанти: А) підробити, скопіювавши (1), або Б) визнати, що ми насправді не знаємо декартових координат, і просто не оновлювати actualPos. Який би підхід не використовувався, я не бачу причин не робити це однаково, незалежно від режиму роботи. Я б запропонував наступне: якщо є прямі кінематичні функції, використовуйте їх, якщо вони не працюють через неверні осі або інші проблеми, в такому випадку виконайте (B). Якщо прямих кінематичних функцій немає, виконайте (A), оскільки в іншому випадку actualPos ніколи не буде оновлено.
7. Самонаведення
7.1. Діаграма стану самонаведення
7.2. Ще одна схема самонаведення
8. Команди
Команди реалізуються за допомогою великого оператора switch у функції emcmotCommandHandler(), яка викликається на швидкості сервоприводу. Докладніше про цю функцію пізніше.
Існує приблизно 44 команди — цей список все ще розробляється.
|
Note
|
Перелік cmd_code_t у файлі motion.h містить 73 команди, але оператор switch у файлі command.c враховує лише 70 команд (станом на 5 червня 2020 року). Команди ENABLE_WATCHDOG / DISABLE_WATCHDOG знаходяться в motion-logger.c. Можливо, вони застаріли. Команда SET_TELEOP_VECTOR з’являється тільки в motion-logger.c і не має ніякого ефекту, крім власного журналу. |
8.1. ABORT
Команда ABORT просто зупиняє всі рухи. Вона може бути видана в будь-який час і завжди буде прийнята. Вона не вимикає контролер руху і не змінює інформацію про стан, а просто скасовує будь-який рух, який виконується в даний момент. Примітка: [Здається, що код вищого рівня (TASK і вище) також використовує ABORT для усунення несправностей. Кожного разу, коли виникає постійна помилка (наприклад, вихід за межі апаратних кінцевих вимикачів), код вищого рівня надсилає постійний потік ABORT до контролера руху, намагаючись усунути помилку. Тисячі таких повідомлень… Це означає, що контролер руху повинен уникати постійних помилок. Це потрібно перевірити.]
8.1.1. Вимоги
Жодного. Команда завжди приймається та виконується негайно.
8.1.2. Результати
У вільному режимі планувальники траєкторії вільного режиму відключені. Це призводить до того, що кожен шарнір зупиняється так швидко, як дозволяє його обмеження прискорення (сповільнення). Зупинка не координується. У режимі телеоператора задана декартова швидкість встановлюється на нуль. Я не знаю, до якого саме зупинення це призведе (скоординоване, нескоординоване тощо), але зрештою з’ясую це. У режимі координації планувальник траєкторії в режимі координації отримує команду припинити поточний рух. Знову ж таки, я не знаю, до чого саме це призведе, але задокументую це, коли з’ясую.
8.2. FREE
Команда FREE переводить контролер руху у вільний режим. Вільний режим означає, що кожен шарнір є незалежним від усіх інших шарнірів. У вільному режимі ігноруються декартові координати, позиції та кінематика. По суті, кожен шарнір має власний простий планувальник траєкторії, і кожен шарнір повністю ігнорує інші шарніри. Деякі команди (наприклад, Joint JOG і HOME) працюють тільки у вільному режимі. Інші команди, включаючи всі, що мають відношення до декартових координат, у вільному режимі не працюють взагалі.
8.2.1. Вимоги
Обробник команд не застосовує жодних вимог до команди FREE, вона завжди буде прийнята. Однак, якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), то команда буде проігнорована. Ця поведінка контролюється кодом, який зараз знаходиться у функції set_operating_mode() в control.c, цей код потрібно очистити. Я вважаю, що команда не повинна ігноруватися без повідомлення, натомість обробник команд повинен визначати, чи може вона бути виконана, і повертати помилку, якщо це неможливо.
8.2.2. Результати
Якщо машина вже перебуває у вільному режимі, нічого не відбувається. В іншому випадку машина переводиться у вільний режим. Планувальник траєкторії вільного режиму кожного суглоба ініціалізується до поточного положення суглоба, але планувальники не вмикаються, а суглоби залишаються нерухомими.
8.3. TELEOP
Команда TELEOP переводить машину в режим телеуправління. У режимі телеуправління рух машини базується на декартових координатах з використанням кінематики, а не на окремих суглобах, як у вільному режимі. Однак сам по собі планувальник траєкторії не використовується, натомість рух контролюється вектором швидкості. Рух у режимі телеуправління дуже схожий на біг підтюпцем, за винятком того, що він здійснюється в декартовому просторі, а не в просторі суглобів. На машині з тривіальною кінематикою різниця між режимом телеоперації та вільним режимом незначна, і графічні інтерфейси для таких машин можуть навіть ніколи не видавати цю команду. Однак для нетривіальних машин, таких як роботи та гексаподи, режим телеоперації використовується для більшості рухів типу бігу, що виконуються за командою користувача.
8.3.1. Вимоги
Командний обробник відхилить команду TELEOP з повідомленням про помилку, якщо кінематика не може бути активована через те, що один або декілька шарнірів не були повернені в початкове положення. Крім того, якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), команда буде проігнорована (без повідомлення про помилку). Ця поведінка контролюється кодом, який зараз знаходиться у функції set_operating_mode() в control.c. Я вважаю, що команда не повинна бути проігнорована без повідомлення, натомість обробник команд повинен визначити, чи може вона бути виконана, і повернути помилку, якщо це неможливо.
8.3.2. Результати
Якщо машина вже перебуває в режимі телеоператора, нічого не відбувається. В іншому випадку машина переводиться в режим телеоператора. Активується кінематичний код, інтерполятори спорожнюються і промиваються, а декартові команди швидкості встановлюються на нуль.
8.4. COORD
Команда COORD переводить верстат у координаційний режим. У координаційному режимі рух верстата базується на декартових координатах з використанням кінематики, а не на окремих з’єднаннях, як у вільному режимі. Крім того, для генерації руху використовується основний планувальник траєкторії на основі команд LINE, CIRCLE та/або PROBE, що знаходяться в черзі. Координаційний режим використовується під час виконання програми G-коду.
8.4.1. Вимоги
Командний обробник відхилить команду COORD з повідомленням про помилку, якщо кінематику неможливо активувати через те, що один або декілька шарнірів не повернулися в початкове положення. Крім того, якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), команда буде проігнорована (без повідомлення про помилку). Ця поведінка контролюється кодом, який зараз знаходиться у функції set_operating_mode() в control.c. Я вважаю, що команда не повинна бути проігнорована без повідомлення, натомість обробник команд повинен визначити, чи може вона бути виконана, і повернути помилку, якщо це неможливо.
8.4.2. Результати
Якщо верстат вже перебуває в режимі координат, нічого не відбувається. В іншому випадку верстат переводиться в режим координат. Активується кінематичний код, інтерполятори спорожнюються і очищаються, а черги планувальника траєкторій спорожнюються. Планувальник траєкторій активний і очікує команди LINE, CIRCLE або PROBE.
8.5. ENABLE
Команда ENABLE вмикає контролер руху.
8.5.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.5.2. Результати
Якщо контролер вже увімкнено, нічого не відбувається. Якщо ні, контролер увімкнено. Черги та інтерполятори очищуються. Будь-які операції переміщення або повернення в початкове положення припиняються. Виходи увімкнення підсилювача, пов’язані з активними з’єднаннями, увімкнено. Якщо пряма кінематика недоступна, машина переходить у вільний режим.
8.6. DISABLE
Команда DISABLE вимикає контролер руху.
8.6.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.6.2. Результати
Якщо контролер вже вимкнений, нічого не відбувається. Якщо ні, контролер вимикається. Черги та інтерполятори очищаються. Будь-які операції переміщення або повернення в вихідне положення припиняються. Виходи підсилення, пов’язані з активними з’єднаннями, вимикаються. Якщо пряма кінематика недоступна, машина переходить у вільний режим.
8.7. ENABLE_AMPLIFIER
Команда ENABLE_AMPLIFIER вмикає вихід увімкнення підсилювача для підсилювача з одним виходом, не змінюючи нічого іншого. Може використовуватися для ввімкнення контролера швидкості шпинделя.
8.7.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.7.2. Результати
Наразі нічого. (Виклик старої функції extAmpEnable наразі закоментовано.) Зрештою, це встановить пін HAL увімкнення підсилювача в значення true.
8.8. DISABLE_AMPLIFIER
Команда DISABLE_AMPLIFIER вимикає вихід увімкнення підсилювача для одного підсилювача, не змінюючи нічого іншого. Знову ж таки, корисно для контролерів швидкості шпинделя.
8.8.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.8.2. Результати
Наразі нічого. (Виклик старої функції extAmpEnable наразі закоментовано.) Зрештою, це встановить пін HAL увімкнення підсилювача у значення false.
8.9. ACTIVATE_JOINT
Команда ACTIVATE_JOINT вмикає всі обчислення, пов’язані з одним з’єднанням, але не змінює вихідний контакт увімкнення підсилювача цього з’єднання.
8.9.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.9.2. Результати
Розрахунки для зазначеного з’єднання ввімкнено. Вивід увімкнення підсилювача не змінюється, проте будь-які наступні команди ENABLE або DISABLE змінять вивід увімкнення підсилювача з’єднання.
8.10. DEACTIVATE_JOINT
Команда DEACTIVATE_JOINT вимикає всі обчислення, пов’язані з одним з’єднанням, але не змінює вихідний контакт увімкнення підсилювача цього з’єднання.
8.10.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.10.2. Результати
Розрахунки для вказаного з’єднання ввімкнено. Вивід увімкнення підсилювача не змінюється, а наступні команди ENABLE або DISABLE не змінять вивід увімкнення підсилювача з’єднання.
8.11. ENABLE_WATCHDOG
Команда ENABLE_WATCHDOG вмикає апаратний сторожовий таймер (якщо він присутній).
8.11.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.11.2. Результати
Наразі нічого. Старий сторожовий таймер був дивною річчю, яка використовувала певну звукову карту. Новий інтерфейс сторожового таймера може бути розроблений у майбутньому.
8.12. DISABLE_WATCHDOG
Команда DISABLE_WATCHDOG вимикає апаратний сторожовий таймер (якщо він присутній).
8.12.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.12.2. Результати
Наразі нічого. Старий сторожовий таймер був дивною річчю, яка використовувала певну звукову карту. Новий інтерфейс сторожового таймера може бути розроблений у майбутньому.
8.13. PAUSE
Команда PAUSE зупиняє планувальник траєкторії. Вона не діє в режимі вільного або телеоперативного керування. На даний момент я не знаю, чи вона негайно зупиняє всі рухи, чи завершує поточний рух, а потім зупиняється, перш ніж витягнути інший рух із черги.
8.13.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.13.2. Результати
Планувальник траєкторії зупиняється.
8.14. RESUME
Команда RESUME перезапускає планувальник траєкторії, якщо він призупинений. Вона не має жодного ефекту у вільному режимі або режимі телеоп, або якщо планувальник не призупинений.
8.14.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.14.2. Результати
Планувальник траєкторії відновлює роботу.
8.15. STEP
Команда STEP перезапускає планувальник траєкторії, якщо він призупинений, і дає йому команду зупинитися знову, коли він досягне певної точки. Вона не діє в режимі вільного або телеоперативного керування. На даний момент я не знаю, як саме це працює. Я додам більше інформації, коли глибше вивчу планувальник траєкторії.
8.15.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.15.2. Результати
Планувальник траєкторії відновлює роботу, а потім зупиняється, коли досягає певної точки.
8.16. SCALE
Команда SCALE масштабує всі обмеження швидкості та команди на задану величину. Вона використовується для реалізації перевизначення швидкості подачі та інших подібних функцій. Масштабування працює в режимах free, teleop та coord і впливає на все, включаючи швидкості повернення в вихідне положення тощо. Однак індивідуальні обмеження швидкості суглобів не змінюються.
8.16.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята.
8.16.2. Результати
Усі команди швидкості масштабуються на задану константу.
8.17. OVERRIDE_LIMITS
Команда OVERRIDE_LIMITS запобігає спрацьовуванню обмежень до кінця наступної команди JOG. Зазвичай вона використовується для того, щоб машина могла відійти від кінцевого вимикача після спрацьовування. (Команда може бути використана для перевизначення обмежень або для скасування попереднього перевизначення.)
8.17.1. Вимоги
Жодної. Команду можна видати будь-коли, і вона завжди буде прийнята. (Я думаю, що вона має працювати лише у вільному режимі.)
8.17.2. Результати
Обмеження на всі з’єднання ігноруються до кінця наступної команди JOG. (Наразі ця функція не працює… після отримання команди OVERRIDE_LIMITS обмеження ігноруються, доки інша команда OVERRIDE_LIMITS не увімкне їх знову.)
8.18. HOME
Команда HOME ініціює послідовність повернення в початкове положення на вказаному з’єднанні. Фактична послідовність повернення в початкове положення визначається низкою параметрів конфігурації і може варіюватися від простого встановлення поточного положення на нуль до багатоетапного пошуку перемикача початкового положення та імпульсу індексу, після чого відбувається переміщення до довільного початкового положення. Докладнішу інформацію про послідовність повернення в початкове положення див. у розділі «Повернення в початкове положення» посібника з інтегратора.
8.18.1. Вимоги
Команда буде проігнорована без попереднього налаштування, якщо машина не перебуває у вільному режимі.
8.18.2. Результати
Будь-який поштовх або інший рух суглоба переривається, і починається послідовність повернення до початкового положення.
8.19. JOG_CONT
Команда JOG_CONT ініціює безперервний поступальний рух на одному суглобі. Безперервний поступальний рух генерується шляхом встановлення цільової позиції планувальника траєкторії у вільному режимі на точку, що знаходиться за межами діапазону переміщення суглоба. Це гарантує, що планувальник буде рухатися постійно, доки його не зупинять межі суглоба або команда ABORT. Зазвичай графічний інтерфейс користувача надсилає команду JOG_CONT, коли користувач натискає кнопку поступального руху, і команду ABORT, коли кнопка відпускається.
8.19.1. Вимоги
Командний обробник відхилить команду JOG_CONT з повідомленням про помилку, якщо машина не перебуває у вільному режимі, або якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), або якщо рух не ввімкнено. Він також мовчки проігнорує команду, якщо шарнір вже знаходиться на межі або за межею свого діапазону, і заданий рух погіршить ситуацію.
8.19.2. Результати
Активується планувальник траєкторії вільного режиму для суглоба, ідентифікованого emcmotCommand->axis, з цільовою позицією за межами кінця ходу суглоба та обмеженням швидкості emcmotCommand->vel. Це запускає рух суглоба, і рух триватиме, доки не буде зупинений командою ABORT або досягненням межі. Планувальник вільного режиму прискорюється до межі прискорення суглоба на початку руху і сповільнюється до межі прискорення суглоба, коли зупиняється.
8.20. JOG_INCR
Команда JOG_INCR ініціює інкрементний поштовх на одному шарнірі. Інкрементні поштовхи є кумулятивними, іншими словами, видача двох команд JOG_INCR, кожна з яких вимагає переміщення на 0,100 дюйма, призведе до переміщення на 0,200 дюйма, навіть якщо друга команда видається до завершення першої. Зазвичай інкрементальні переміщення зупиняються, коли вони проходять бажану відстань, однак вони також зупиняються, коли досягають межі або при виконанні команди ABORT.
8.20.1. Вимоги
Команда обробки буде мовчки відхиляти команду JOG_INCR, якщо машина не перебуває у вільному режимі, або якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), або якщо рух не ввімкнено. Вона також мовчки ігноруватиме команду, якщо шарнір вже знаходиться на межі або за межею, і заданий рух погіршить ситуацію.
8.20.2. Результати
Активується планувальник траєкторії вільного режиму для з’єднання, ідентифікованого emcmotCommand->axis, цільове положення збільшується/зменшується на emcmotCommand->offset, а обмеження швидкості встановлюється на emcmotCommand->vel. Планувальник траєкторії вільного режиму генерує плавний трапецієподібний рух від поточного положення до цільового положення. Планувальник може правильно обробляти зміни в цільовому положенні, що відбуваються під час руху, тому можна швидко послідовно видавати кілька команд JOG_INCR. Планувальник вільного режиму прискорюється до межі прискорення суглоба на початку руху і сповільнюється до межі прискорення суглоба, щоб зупинитися в цільовому положенні.
8.21. JOG_ABS
Команда JOG_ABS ініціює абсолютне переміщення на одному суглобі. Абсолютне переміщення — це просте переміщення до певного місця в координатах суглоба. Зазвичай абсолютні переміщення зупиняються, коли досягають бажаного місця, однак вони також зупиняються, коли досягають межі або за командою ABORT.
8.21.1. Вимоги
Команда обробки буде мовчки відхиляти команду JOG_ABS, якщо машина не перебуває у вільному режимі, або якщо будь-який шарнір знаходиться в русі (GET_MOTION_INPOS_FLAG() == FALSE), або якщо рух не ввімкнено. Вона також мовчки ігноруватиме команду, якщо шарнір вже знаходиться на межі або за межею, і заданий рух погіршить ситуацію.
8.21.2. Результати
Активується планувальник траєкторії вільного режиму для з’єднання, ідентифікованого emcmotCommand->axis, цільове положення встановлюється на emcmotCommand->offset, а обмеження швидкості встановлюється на emcmotCommand->vel. Планувальник траєкторії вільного режиму генерує плавний трапецієподібний рух від поточного положення до цільового положення. Планувальник може правильно обробляти зміни в цільовому положенні, що відбуваються під час руху. Якщо кілька команд JOG_ABS видаються швидко поспіль, кожна нова команда змінює цільове положення, і машина переходить до кінцевого заданого положення. Планувальник вільного режиму прискорюється до межі прискорення суглоба на початку руху і сповільнюється до межі прискорення суглоба, щоб зупинитися в цільовому положенні.
8.22. SET_LINE
Команда SET_LINE додає пряму лінію до черги планувальника траєкторії.
(Більше пізніше)
8.23. SET_CIRCLE
Команда SET_CIRCLE додає круговий рух до черги планувальника траєкторії.
(Більше пізніше)
8.24. SET_TELEOP_VECTOR
Команда SET_TELEOP_VECTOR наказує контролеру руху рухатися вздовж певного вектора в декартовому просторі.
(Більше пізніше)
8.25. PROBE
Команда PROBE дає інструкцію контролеру руху рухатися до певної точки в декартовому просторі, зупиняючись та записуючи своє положення, якщо спрацьовує вхід зонда.
(Більше пізніше)
8.26. CLEAR_PROBE_FLAG
Команда CLEAR_PROBE_FLAG використовується для скидання вхідного сигналу зонда під час підготовки до команди PROBE. (Запитання: чому команда PROBE не повинна автоматично скидати вхідний сигнал?)
(Більше пізніше)
8.27. SET_xix
Існує приблизно 15 команд SET_xxx, де xxx — це назва певного параметра конфігурації. Очікується, що з додаванням нових параметрів з’явиться ще кілька команд SET. Я хотів би знайти більш чіткий спосіб налаштування та зчитування параметрів конфігурації. Існуючі методи вимагають додавання багатьох рядків коду до декількох файлів кожного разу, коли додається новий параметр. Більша частина цього коду є ідентичною або майже ідентичною для кожного параметра.
9. Компенсація люфту та похибки гвинта
Компенсація люфту та помилки гвинта FIXME
10. Контролер завдань (EMCTASK)
10.1. Штат
Завдання має три можливі внутрішні стани: Аварійна зупинка, Скидання аварійної зупинки та Встановлення ввімкнено.
11. Контролер вводу-виводу (EMCIO)
Контролер вводу/виводу є частиною TASK. Він взаємодіє із зовнішніми пристроями вводу/виводу за допомогою контактів HAL.
Наразі ESTOP/Enable, подача охолоджувальної рідини та зміна інструменту обробляються iocontrol. Це події з відносно низькою швидкістю, тоді як високошвидкісний координований ввід/вивід обробляється під час руху.
emctaskmain.cc надсилає команди вводу/виводу через taskclass.cc.
Процес основного циклу iocontrol:
-
перевіряє, чи змінилися входи HAL
-
перевіряє, чи read_tool_inputs() вказує на завершення зміни інструменту, та встановлює emcioStatus.status
12. Інтерфейс користувача
FIXME User Interfaces
13. Вступ до libnml
libnml походить від NIST rcslib без підтримки всіх платформ. Багато обгортків навколо коду, специфічного для платформи, було видалено разом із значною частиною коду, який не потрібен LinuxCNC. Сподіваємося, що сумісність із rcslib залишиться достатньою, щоб програми можна було реалізувати на платформах, відмінних від Linux, і вони все одно могли б спілкуватися з LinuxCNC.
Цей розділ не є вичерпним посібником з використання libnml (або rcslib), а надає загальний огляд кожного класу C++ та їхніх членів-функцій. Спочатку більшість цих приміток будуть випадковими коментарями, доданими під час ретельного вивчення та модифікації коду.
14. Зв’язаний список
Базовий клас для підтримки зв’язаного списку. Це один з основних структурних блоків, що використовуються для передачі NML-повідомлень та різноманітних внутрішніх структур даних.
15. Вузол зв’язаного списку
Базовий клас для створення зв’язаного списку - Призначення: зберігати вказівники на попередній та наступний вузли, вказівник на дані та розмір даних.
Пам’ять для зберігання даних не виділяється.
16. Спільна пам’ять
Надає блок спільної пам’яті разом із семафором (успадкованим від класу Semaphore). Створення та знищення семафора обробляється конструктором та деструктором SharedMemory.
17. ShmBuffer
Клас для передачі NML-повідомлень між локальними процесами з використанням спільного буфера пам’яті. Значна частина внутрішніх механізмів успадкована від класу CMS.
18. Таймер
Клас Timer забезпечує періодичний таймер, обмежений лише роздільною здатністю системного годинника. Якщо, наприклад, процес потрібно запускати кожні 5 секунд незалежно від часу, необхідного для його виконання, наступний фрагмент коду демонструє, як це зробити:
main() { timer = new Timer(5.0); /* Ініціалізувати таймер на 5 секунд loop */ while(0) { /* Виконайте певний процес */ timer.wait(); /* Зачекайте до наступного 5-секундного інтервалу*/ } delete timer; }
19. Семафор
Клас Semaphore надає метод взаємного виключення для доступу до спільного ресурсу. Функція отримання семафора може або блокувати доступ доти, доки він не стане доступним, або повертатися після закінчення часу очікування, або повертатися негайно з отриманням семафора чи без нього. Конструктор створить семафор або приєднається до існуючого, якщо ідентифікатор вже використовується.
Semaphore::destroy() має викликатися лише останнім процесом.
20. CMS
В основі libnml лежить клас CMS, який містить більшість функцій, що використовуються libnml і, зрештою, NML. Багато внутрішніх функцій перевантажені, щоб забезпечити специфічні, залежні від апаратного забезпечення методи передачі даних. Зрештою, все обертається навколо центрального блоку пам’яті (який називається «буфером повідомлень» або просто «буфером»). Цей буфер може існувати як блок спільної пам’яті, до якого мають доступ інші процеси CMS/NML, або як локальний і приватний буфер для даних, що передаються через мережу або послідовні інтерфейси.
Буфер динамічно розподіляється під час виконання, щоб забезпечити більшу гнучкість підсистеми CMS/NML. Розмір буфера повинен бути достатньо великим, щоб вмістити найбільше повідомлення, невелику кількість для внутрішнього використання та дозволити кодування повідомлення, якщо обрано цю опцію (кодовані дані будуть розглянуті пізніше). Наступний малюнок є внутрішнім видом простору буфера.
Базовий клас CMS в першу чергу відповідає за створення комунікаційних шляхів та взаємодію з операційною системою.
21. Формат файлу конфігурації
Конфігурація NML складається з двох типів форматів рядків. Один для буферів, а другий для процесів, які підключаються до буферів.
21.1. Буферна лінія
Оригінальний формат буферного рядка NIST такий:
-
B ім’я тип розмір хоста neutr RPC# buffer# max_procs ключ [конфігурації, специфічні для типу]
-
«B» – ідентифікує цю лінію як конфігурацію буфера.
-
name – ідентифікатор буфера.
-
type – описує тип буфера – SHMEM, LOCMEM, FILEMEM, PHANTOM або GLOBMEM.
-
host – це або IP-адреса, або ім’я хоста для NML-сервера
-
size – це розмір буфера
-
neut – логічне значення, яке вказує, чи дані в буфері закодовані в машинно-незалежному форматі, чи в необробленому вигляді.
-
RPC# – Застарілий – Заповнювач збережено лише для зворотної сумісності.
-
buffer# – унікальний ідентифікаційний номер, який використовується, якщо сервер керує кількома буферами.
-
max_procs – максимальна кількість процесів, яким дозволено підключатися до цього буфера.
-
ключ – це числовий ідентифікатор буфера спільної пам’яті
21.2. Конфігурації, що відповідають певному типу
Тип буфера передбачає додаткові параметри конфігурації, тоді як операційна система хоста виключає певні комбінації. З метою узагальнення опублікованої документації в єдиному форматі, буде розглянуто лише тип буфера SHMEM.
-
mutex=os_sem – режим за замовчуванням для забезпечення блокування буферної пам’яті семафорами.
-
mutex=none – Не використовується
-
mutex=no_interrupts – не застосовується в системі Linux
-
mutex=no_switching – не застосовується в системі Linux
-
mutex=mao split – Розділяє буфер навпіл (або більше) та дозволяє одному процесу отримувати доступ до частини буфера, поки інший процес записує дані в іншу частину.
-
TCP=(номер порту) – Вказує, який мережевий порт використовувати.
-
UDP=(номер порту) - те саме
-
STCP=(номер порту) - те саме
-
serialPortDevName=(послідовний порт) – Недокументовано.
-
passwd=ім’я_файлу.pwd – Додає рівень безпеки до буфера, вимагаючи від кожного процесу введення пароля.
-
bsem – документація NIST передбачає ключ для блокувального семафора, і якщо bsem=-1, блокування читання запобігається.
-
queue – Вмикає передачу повідомлень у чергу.
-
ascii - Кодування повідомлень у форматі звичайного тексту
-
disp - Кодувати повідомлення у форматі, придатному для відображення (???)
-
xdr – Кодувати повідомлення у зовнішньому представленні даних. (докладніше див. rpc/xdr.h).
-
diag - Вмикає збереження діагностичних даних у буфері (таймінг та кількість байтів?)
21.3. Технологічна лінія
Оригінальний формат NIST для технологічної лінії такий:
P ім’я буфер тип хост-операції сервер тайм-аут master c_num [конфігурації, специфічні для типу]
-
«P» – ідентифікує цей рядок як конфігурацію процесу.
-
name – це ідентифікатор процесу.
-
buffer – один із буферів, визначених в іншому місці конфігураційного файлу.
-
type – визначає, чи є цей процес локальним чи віддаленим відносно буфера.
-
host – вказує, де в мережі виконується цей процес.
-
ops – надає процесу доступ до буфера лише для читання, лише для запису або для читання/запису.
-
server – вказує, чи цей процес запускатиме сервер для цього буфера.
-
timeout - встановлює характеристики тайм-ауту для звернень до буфера.
-
master - вказує, чи відповідає цей процес за створення та знищення буфера.
-
c_num - ціле число від нуля до (max_procs -1)
21.4. Коментарі до конфігурації
Деякі комбінації конфігурацій є недійсними, тоді як інші передбачають певні обмеження. У системі Linux GLOBMEM є застарілим, тоді як PHANTOM є дійсно корисним лише на етапі тестування програми, так само як і FILEMEM. LOCMEM є малокорисним для багатопроцесорних програм і пропонує лише обмежені переваги в продуктивності порівняно з SHMEM. Таким чином, SHMEM залишається єдиним типом буфера, який можна використовувати з LinuxCNC.
Опція neut використовується тільки в багатопроцесорних системах, де різні (і несумісні) архітектури спільно використовують блок пам’яті. Імовірність побачити систему такого типу поза музеєм або науково-дослідною установою є дуже низькою і стосується тільки буферів GLOBMEM.
Номер RPC задокументовано як застарілий і зберігається лише з міркувань сумісності.
З унікальним іменем буфера наявність числового ідентифікатора здається безглуздою. Необхідно переглянути код, щоб визначити логіку. Аналогічно, поле ключа спочатку здається зайвим, і його можна отримати з імені буфера.
Мета обмеження кількості процесів, яким дозволено підключатися до будь-якого одного буфера, неясна з існуючої документації та з оригінального вихідного коду. Дозволити невизначеній кількості процесів підключатися до буфера не складніше реалізувати.
Типи мьютексів зводяться до одного з двох: стандартного «os_sem» або «mao split». Більшість повідомлень NML є відносно короткими і можуть бути скопійовані в буфер або з нього з мінімальною затримкою, тому роздільне читання не є необхідним.
Кодування даних є актуальним лише при передачі до віддаленого процесу - використання TCP або UDP передбачає кодування XDR. Кодування ASCII може бути корисним для діагностики або передачі даних до вбудованої системи, яка не підтримує NML.
Протоколи UDP мають менше перевірок даних і дозволяють відкидати певний відсоток пакетів. TCP є надійнішим, але трохи повільнішим.
Якщо LinuxCNC підключається до мережі, бажано, щоб це була локальна мережа за брандмауером. Єдина причина, яка може виправдати доступ до LinuxCNC через Інтернет, — це дистанційна діагностика. Однак це можна зробити набагато безпечніше іншими способами, наприклад, за допомогою веб-інтерфейсу.
Точна поведінка, коли час очікування встановлений на нуль або від’ємне значення, не зрозуміла з документів NIST. Згадуються тільки INF і додатні значення. Однак, занурившись у вихідний код rcslib, стає очевидним, що застосовується наступне:
- timeout > 0
-
Blocking access until the timeout interval is reached or access to the buffer is available.
- timeout = 0
-
Access to the buffer is only possible if no other process is reading or writing at the time.
- timeout < 0 or INF
-
Access is blocked until the buffer is available.
22. Базовий клас NML
Розгорніть списки та зв’язок між NML, NMLmsg та класами CMS нижчого рівня.
Не слід плутати з NMLmsg, RCS_STAT_MSG або RCS_CMD_MSG.
NML відповідає за розбір конфігураційного файлу, налаштування буферів cms та є механізмом маршрутизації повідомлень до правильного(их) буфера(ів). Для цього NML створює кілька списків для:
-
створені або підключені буфери cms.
-
процеси та буфери, до яких вони підключаються
-
довгий список функцій форматування для кожного типу повідомлення
Останній пункт, ймовірно, є основною причиною багатьох нарікань на libnml/rcslib та NML загалом. Кожне повідомлення, що передається через NML, вимагає додавання певної кількості інформації, окрім власне даних. Для цього послідовно викликаються кілька функцій форматування, щоб зібрати фрагменти загального повідомлення. Функції форматування включатимуть NML_TYPE, MSG_TYPE, крім даних, оголошених у похідних класах NMLmsg. Зміни в порядку виклику функцій форматування, а також переданих змінних порушать сумісність з rcslib, якщо з ними погратися. Є причини для збереження сумісності з rcslib, і є вагомі причини для втручання в код. Питання в тому, які з цих причин є більш вагомими?
22.1. Внутрішні механізми NML
22.1.1. Конструктор NML
NML::NML() аналізує файл конфігурації та зберігає його у зв’язаному списку, який передається конструкторам cms у вигляді окремих рядків. Функція конструктора NML полягає у виклику відповідного конструктора cms для кожного буфера та підтримці списку об’єктів cms і процесів, пов’язаних з кожним буфером.
Саме за допомогою вказівників, що зберігаються у списках, NML може взаємодіяти з CMS, і саме тому Doxygen не показує реальні взаємозв’язки.
|
Note
|
Конфігурація зберігається в пам’яті перед передачею покажчика на конкретний рядок до конструктора cms. Потім конструктор cms знову аналізує рядок, щоб витягти кілька змінних… Було б доцільніше виконати ВЕСЬ аналіз і зберегти змінні в структурі, яка передається до конструктора cms. Це дозволило б уникнути обробки рядків і зменшити кількість дублювання коду в cms… |
22.1.2. Читання/запис NML
Виклики NML::read і NML::write виконують подібні завдання в частині обробки повідомлення. Єдина реальна відмінність полягає в напрямку потоку даних.
Виклик функції читання спочатку отримує дані з буфера, а потім викликає format_output(), тоді як функція запису викликає format_input() перед передачею даних до буфера. Саме в format_xxx() відбувається побудова або деконструкція повідомлення. Список різних функцій викликається по черзі, щоб розмістити різні частини заголовка NML (не плутати з заголовком cms) у правильному порядку. Остання функція, що викликається, — emcFormat() у emc.cc.
22.1.3. NMLmsg та зв’язки NML
NMLmsg — це базовий клас, від якого походять усі класи повідомлень. Кожен клас повідомлень повинен мати унікальний ідентифікатор (який передається конструктору) та функцію update(*cms). Функція update() викликається функціями читання/запису NML під час виклику форматувальника NML — покажчик на форматувальник буде оголошений у конструкторі NML у певний момент. Завдяки зв’язаним спискам, які створює NML, він може вибрати покажчик cms, який передається до форматувальника, і, отже, який буфер буде використовуватися.
23. Додавання власних команд NML
LinuxCNC - це чудова програма, але деякі її частини потребують доопрацювання. Як відомо, комунікація здійснюється через канали NML, а дані, що надсилаються через такий канал, є одним із класів, визначених у emc.hh (реалізовано в emc.cc). Якщо комусь потрібен тип повідомлення, якого не існує, він повинен виконати наступні кроки, щоб додати новий. (Повідомлення, яке я додав у прикладі, називається EMC_IO_GENERIC (успадковує EMC_IO_CMD_MSG (успадковує RCS_CMD_MSG)))
-
додати визначення класу EMC_IO_GENERIC до emc2/src/emc/nml_intf/emc.hh
-
add the type define: #define EMC_IO_GENERIC_TYPE \((NMLTYPE) 1605)
-
(Я обрав 1605, бо він був доступний) до emc2/src/emc/nml_intf/emc.hh
-
-
додати регістр EMC_IO_GENERIC_TYPE до emcFormat у emc2/src/emc/nml_intf/emc.cc
-
додати регістр EMC_IO_GENERIC_TYPE до emc_symbol_lookup в emc2/src/emc/nml_intf/emc.cc
-
додати функцію EMC_IO_GENERIC::update до emc2/src/emc/nml_intf/emc.cc
Перекомпілюйте, і нове повідомлення має бути там. Наступний етап — надсилати такі повідомлення звідкись, отримувати їх в іншому місці та робити з ними якісь дії.
24. Стіл інструментів та змінник інструментів
LinuxCNC взаємодіє з апаратним забезпеченням змінника інструментів та має внутрішню абстракцію змінника інструментів. LinuxCNC керує інформацією про інструменти у файлі таблиці інструментів.
24.1. Абстракція Toolchanger у LinuxCNC
LinuxCNC підтримує два типи апаратного забезпечення для зміни інструментів, які називаються nonrandom та random. Налаштування INI [EMCIO]RANDOM_TOOLCHANGER визначає, до якого з цих типів апаратного забезпечення підключено LinuxCNC.
24.1.1. Невипадкові змінники інструментів
Апаратне забезпечення невипадкового змінника інструментів повертає кожен інструмент у гніздо, з якого його було спочатку завантажено.
Прикладами обладнання для невипадкової зміни інструментів є "ручний" змінник інструментів, токарні інструментальні револьвери та рейкові змінники інструментів.
При налаштуванні для невипадкового змінювача інструментів LinuxCNC не змінює номер кишені у файлі таблиці інструментів під час завантаження та вивантаження інструментів. Всередині LinuxCNC під час зміни інструменту інформація про інструмент копіюється з вихідної кишені таблиці інструментів до кишені 0 (яка представляє шпиндель), замінюючи будь-яку інформацію про інструмент, яка була там раніше.
|
Note
|
У LinuxCNC, налаштованому для невипадкового змінювача інструментів, інструмент 0 (T0) має особливе значення: «відсутність інструменту». T0 може не з’являтися у файлі таблиці інструментів, і перехід на T0 призведе до того, що LinuxCNC вважатиме, що шпиндель порожній. |
24.1.2. Випадкові змінники інструментів
Апаратне забезпечення для випадкової зміни інструментів замінює інструмент у шпинделі (якщо такий є) на запитуваний інструмент під час зміни інструменту. Таким чином, гніздо, в якому знаходиться інструмент, змінюється під час його вставки та виставки зі шпинделя.
Прикладом обладнання для випадкової зміни інструментів є карусельний змінник інструментів.
При налаштуванні для випадкового змінювача інструментів LinuxCNC обмінює номерами кишені старого та нового інструменту у файлі таблиці інструментів під час завантаження інструментів. Всередині LinuxCNC під час зміни інструменту інформація про інструмент обмінюється між вихідною кишенею таблиці інструментів та кишенею 0 (яка представляє шпиндель). Отже, після зміни інструменту кишеня 0 в таблиці інструментів містить інформацію про новий інструмент, а кишеня, з якої походить новий інструмент, містить інформацію про старий інструмент (інструмент, який був у шпинделі до зміни інструменту), якщо така є.
|
Note
|
Якщо LinuxCNC налаштований для випадкового перемикання інструментів, інструмент 0 (T0) не має жодного особливого значення. Він розглядається так само, як і будь-який інший інструмент у таблиці інструментів. Зазвичай T0 використовується для позначення «відсутності інструменту» (тобто інструменту з нульовим TLO), щоб у разі потреби можна було зручно звільнити шпиндель. |
24.2. Стіл інструментів
LinuxCNC відстежує інструменти у файлі під назвою tool table. У таблиці інструментів записується така інформація для кожного інструменту:
- номер інструменту
-
Ціле число, яке однозначно ідентифікує цей інструмент. Номери інструментів обробляються LinuxCNC по-різному, коли вони налаштовані для випадкових та невипадкових змінників інструментів:
-
Коли LinuxCNC налаштовано для невипадкового змінника інструментів, це число має бути додатним. T0 отримує спеціальну обробку та не може з’являтися в таблиці інструментів.
-
Коли LinuxCNC налаштовано для випадкового пристрою зміни інструментів, це число має бути невід’ємним. T0 дозволено в таблиці інструментів і зазвичай використовується для позначення "відсутності інструменту", тобто порожнього гнізда.
-
- номер кишені
-
Ціле число, яке ідентифікує кишеню або слот в апаратному забезпеченні змінювача інструментів, де знаходиться інструмент. Номери кишень обробляються LinuxCNC по-різному, якщо він налаштований для випадкових і невипадкових змінювачів інструментів:
-
Коли LinuxCNC налаштований для невипадкового змінювача інструментів, номер кишені в файлі інструментів може бути будь-яким додатним цілим числом (кишеня 0 не допускається). LinuxCNC без попередження ущільнює номери кишень під час завантаження файлу інструментів, тому можуть бути відмінності між номерами кишень у файлі інструментів та внутрішніми номерами кишень, що використовуються LinuxCNC з невипадковим змінювачем інструментів.
-
Коли LinuxCNC налаштовано для випадкового змінника інструментів, номери гнізд у файлі інструментів повинні бути від 0 до 1000 включно. Гнізда 1-1000 знаходяться в зміннику інструментів, гніздо 0 – це шпиндель.
-
- діаметр
-
Діаметр інструменту, в одиницях виміру.
- зміщення довжини інструмента
-
Зміщення довжини інструменту (також відоме як TLO) до 9 осей, в одиницях машинного вимірювання. Осі, які не мають заданого TLO, отримують значення 0.
24.3. G-коди, що впливають на інструменти
G-коди, які використовують або впливають на інформацію про інструмент:
24.3.1. Txxx
Наказує апаратному засобу зміни інструментів підготуватися до перемикання на вказаний інструмент xxx.
Обробляється Interp::convert_tool_select().
-
Верстату пропонується підготуватися до перемикання на вибраний інструмент шляхом виклику функції Canon
SELECT_TOOL()з номером запитуваного інструменту.-
(сайканон) Ніякої операції.
-
(emccanon) Створює повідомлення
EMC_TOOL_PREPAREіз запитуваним номером кишені та надсилає його до Task, який надсилає його до IO. IO отримує повідомлення та просить HAL підготувати кишеню, встановившиiocontrol.0.tool-prep-pocket,iocontrol.0.tool-prep-numberтаiocontrol.0.tool-prepare. IO потім неодноразово викликаєread_tool_inputs(), щоб опитувати контакт HALiocontrol.0.tool-prepared, який через HAL сигналізує IO про завершення підготовки інструменту, що запитується, від апаратного забезпечення змінювача інструменту. Коли цей контакт стає True, IO встановлюєemcioStatus.tool.pocketPreppedна номер кишені запитуваного інструменту.
-
-
Повернувшись до інтерфейсу,
settings->selected_pocketотримує індекс tooldata запитуваного інструменту xxx.
|
Note
|
Старі імена selected_pocket та current_pocket насправді посилаються на послідовний індекс tooldata для елементів інструменту, завантажених із таблиці інструментів ([EMCIO]TOOL_TABLE) або через базу даних tooldata ([EMCIO]DB_PROGRAM). |
24.3.2. M6
Наказує зміннику інструментів переключитися на поточний вибраний інструмент (вибраний попередньою командою Txxx).
Обробляється за допомогою Interp::convert_tool_change().
-
Верстату надсилається запит на перемикання на вибраний інструмент шляхом виклику функції Canon
CHANGE_TOOL()зsettings->selected_pocket(індексом даних інструменту).-
(saicanon) Встановлює
_active_slotsai на переданий номер кишені. Інформація про інструмент копіюється з вибраної кишені таблиці інструментів (тобто з_tools[_active_slot]sai) на шпиндель (тобто_tools[0]sai). -
(emccanon) Відправляє повідомлення
EMC_TOOL_LOADдо Task, який відправляє його до IO. IO встановлюєemcioStatus.tool.toolInSpindleна номер інструменту в кишені, ідентифікованійemcioStatus.tool.pocketPrepped(встановлюєтьсяTxxxабоSELECT_TOOL()). Потім він запитує, щоб апаратне забезпечення змінювача інструментів виконало зміну інструменту, встановивши HAL-контактiocontrol.0.tool-changeна True. Пізнішеread_tool_inputs()IO виявить, що контакт HALiocontrol.0.tool_changedвстановлено в значення True, що вказує на те, що змінювач інструменту завершив зміну інструменту. Коли це відбувається, він викликаєload_tool(), щоб оновити стан верстата.-
load_tool()з невипадковою конфігурацією змінника інструментів копіює інформацію про інструмент з вибраного гнізда до шпинделя (гніздо 0). -
load_tool()з випадковою конфігурацією змінювача інструментів обмінює інформацію про інструмент між гніздом 0 (шпиндель) та вибраним гніздом, а потім зберігає таблицю інструментів.
-
-
-
У інтерпретаторі
settings->current_pocketприсвоюється новий індекс tooldata зsettings->selected_pocket(встановленийTxxx). Відповідні пронумеровані параметри (#5400-#5413) оновлюються новою інформацією про інструмент з кишені 0 (шпиндель).
24.3.3. G43/G43.1/G49
Застосувати зміщення довжини інструменту. G43 використовує TLO поточного завантаженого інструменту або вказаного інструменту, якщо в блоці вказано H-слово. G43.1 отримує TLO з осьових слів у блоці. G49 скасовує TLO (використовує 0 для зміщення для всіх осей).
Обробляється за допомогою Interp::convert_tool_length_offset().
-
Спочатку створюється
EmcPose, що містить 9-осьові зміщення, які будуть використовуватися. ДляG43.1ці зміщення інструменту походять від слів осі в поточному блоці. ДляG43ці зміщення походять від поточного (інструменту в кишені 0) або від інструменту, зазначеного словом H в блоці. Для G49 всі зміщення дорівнюють 0. -
Зміщення передаються до функції
USE_TOOL_LENGTH_OFFSET()програми Canon.-
(saicanon) Записує TLO в
_tool_offset. -
(emccanon) Створює повідомлення
EMC_TRAJ_SET_OFFSET, що містить зміщення, і надсилає його до Task. Task копіює зміщення доemcStatus->task.toolOffsetі надсилає їх до Motion за допомогою командиEMCMOT_SET_OFFSET. Motion копіює зміщення вemcmotStatus->tool_offset, де вони використовуються для зміщення майбутніх рухів.
-
-
Повернувшись до інтерпретації, зміщення записуються в
settings->tool_offset. Ефективна кишеня записується вsettings->tool_offset_index, хоча це значення ніколи не використовується.
24.3.4. G10 L1/L10/L11
Змінює таблицю інструментів.
Обробляється за допомогою Interp::convert_setup_tool().
-
Вибирає номер інструменту з P-слова в блоці та знаходить гніздо для цього інструменту:
-
У конфігурації невипадкового змінника інструментів це завжди номер гнізда в зміннику інструментів (навіть коли інструмент знаходиться в шпинделі).
-
При випадковій конфігурації змінювача інструментів, якщо інструмент завантажений, він використовує кишеню 0 (кишеня 0 означає «шпиндель»), а якщо інструмент не завантажений, він використовує номер кишені в змінювачі інструментів. (Ця різниця є важливою.)
-
-
Визначає, якими мають бути нові зміщення.
-
Нова інформація про інструмент (діаметр, зміщення, кути та орієнтація), разом з номером інструмента та номером гнізда, передається до виклику Canon SET_TOOL_TABLE_ENTRY().
-
(saicanon) Скопіювати інформацію про новий інструмент у вказане гніздо (у внутрішній таблиці інструментів sai,
_tools). -
(emccanon) Створіть повідомлення
EMC_TOOL_SET_OFFSETз новою інформацією про інструмент і надішліть його до Task, який передасть його до IO. IO оновлює вказану кишеню у своїй внутрішній копії таблиці інструментів (emcioStatus.tool.toolTable), і якщо вказаний інструмент наразі завантажений (його порівнюють зemcioStatus.tool.toolInSpindle), то нова інформація про інструмент також копіюється до кишені 0 (шпиндель). (FIXME: це невелика помилка, копіювання повинно відбуватися тільки на не випадкових машинах.) Нарешті, IO зберігає нову таблицю інструментів.
-
-
Повертаючись до interp, якщо модифікований інструмент наразі завантажений у шпиндель, а верстат не має випадкового змінювача інструментів, то нова інформація про інструмент копіюється з вихідної кишені інструменту до кишені 0 (шпиндель) у копії таблиці інструментів interp,
settings->tool_table. (Ця копія не потрібна на верстатах з випадковим зміною інструменту, оскільки там інструменти не мають вихідної кишені, і замість цього ми просто оновили інструмент у кишені 0 безпосередньо). Відповідні пронумеровані параметри (#5400-#5413) оновлюються на основі інформації про інструмент у шпинделі (шляхом копіювання інформації зsettings->tool_tableінтерпретатора доsettings->parameters). (FIXME: це невелика помилка, параметри повинні оновлюватися тільки в тому випадку, якщо було змінено поточний інструмент). -
Якщо модифікований інструмент наразі завантажений у шпиндель, а конфігурація призначена для невипадкового змінювача інструментів, то інформація про новий інструмент також записується в кишеню 0 таблиці інструментів за допомогою другого виклику SET_TOOL_TABLE_ENTRY(). (Це друге оновлення таблиці інструментів не потрібне на машинах з випадковим змінювачем інструментів, оскільки там інструменти не мають базової комірки, і замість цього ми просто оновили інструмент безпосередньо в комірці 0.)
24.3.5. M61
Встановити поточний номер інструменту. Це перемикає внутрішнє представлення LinuxCNC того, який інструмент знаходиться в шпинделі, без фактичного переміщення змінника інструментів або заміни будь-яких інструментів.
Обробляється за допомогою Interp::convert_tool_change().
Канон: CHANGE_TOOL_NUMBER()
settings->current_pocket отримує індекс tooldata, який наразі містить інструмент, вказаний аргументом Q-word.
24.3.6. G41/G41.1/G42/G42.1
Увімкнути компенсацію радіуса різця (зазвичай називається компенсація різця).
Обробляється Interp::convert_cutter_compensation_on().
У інтерпретаторі не відбувається виклик Canon, cutter comp. Використовує таблицю інструментів очікуваним чином: якщо вказано номер інструменту D-word, він шукає номер кишені вказаного інструменту в таблиці, а якщо D-word не вказано, використовує кишеню 0 (шпиндель).
24.3.7. G40
Скасувати компенсацію радіуса різця.
Обробляється Interp::convert_cutter_compensation_off().
Немає виклику Canon, корекція різця відбувається в інтерпретаторі. Таблиця інструментів не використовується.
24.4. Внутрішні змінні стану
Це не вичерпний список! Інформація про інструменти поширюється по всьому LinuxCNC.
24.4.1. IO
emcioStatus типу EMC_IO_STAT
- emcioStatus.tool.pocketPrepped
-
Коли IO отримує сигнал від HAL про завершення підготовки змінювача інструменту (після команди
Txxx), ця змінна встановлюється на кишеню запитуваного інструменту. Коли IO отримує сигнал від HAL про завершення самої заміни інструменту (після командиM6), ця змінна скидається до -1. - emcioStatus.tool.toolInSpindle
-
Номер інструменту, встановленого на даний момент у шпинделі. Експортовано на вивід HAL
iocontrol.0.tool-number(s32). - emcioStatus.tool.toolTable[]
-
Масив структур
CANON_TOOL_TABLE, довжиноюCANON_POCKETS_MAX. Завантажується з файлу таблиці інструментів під час запуску і зберігається там після цього. Індекс 0 — це шпиндель, індекси 1-(CANON_POCKETS_MAX-1) — це кишені в змінювачі інструментів. Це повна копія інформації про інструменти, яка зберігається окремо відsettings.tool_tableInterp.
24.4.2. між
settings має тип settings, визначений як struct setup_struct у src/emc/rs274ngc/interp_internal.hh.
- settings.selected_pocket
-
Індекс Tooldata інструмента, обраного востаннє за допомогою
Txxx. - settings.current_pocket
-
Вихідний індекс tooldata інструмента, що наразі знаходиться в шпинделі. Іншими словами: з якого індексу tooldata було завантажено інструмент, що наразі знаходиться в шпинделі.
- settings.tool_table[]
-
Масив інформації про інструменти. Індекс масиву — це «номер кишені» (або «номер слота»). Кишеня 0 — це шпиндель, кишені з 1 по (CANON_POCKETS_MAX-1) — це кишені змінювача інструментів.
- settings.tool_offset_index
-
Невикористано. FIXME: Ймовірно, слід вилучити.
- settings.toolchange_flag
-
Interp встановлює це значення як true при виклику функції CHANGE_TOOL() від Canon. Воно перевіряється в
Interp::convert_tool_length_offset(), щоб вирішити, який індекс tooldata використовувати для G43 (без H-слова):settings->current_pocket, якщо заміна інструменту ще триває, індекс tooldata 0 (шпиндель), якщо заміна інструменту завершена. - settings.random_toolchanger
-
Встановлюється з змінної INI
[EMCIO]RANDOM_TOOLCHANGERпід час запуску. Керує різними логіками обробки таблиці інструментів. (IO також зчитує цю змінну INI і змінює свою поведінку на основі неї. Наприклад, під час збереження таблиці інструментів, випадковий змінювач інструментів зберігає інструмент у шпинделі (кишеня 0), але невипадковий змінювач інструментів зберігає кожен інструмент у його «домашній кишені».) - settings.tool_offset
-
Це змінна
EmcPose.-
Використовується для обчислення положення в різних місцях.
-
Надіслано до Motion через повідомлення
EMCMOT_SET_OFFSET. Все, що робить Motion із зміщеннями, — це експортує їх до контактів HALmotion.0.tooloffset.[xyzabcuvw]. FIXME: експортуйте їх з місця, ближчого до таблиці інструментів (ймовірно, io або interp), і видаліть повідомлення EMCMOT_SET_OFFSET.
-
- settings.pockets_max
-
Використовується взаємозамінно з
CANON_POCKETS_MAX(#визначена константа, встановлена на 1000 станом на квітень 2020 року). ВИПРАВЛЕННЯ: Ця змінна налаштувань наразі не є корисною та, ймовірно, її слід вилучити. - settings.tool_table
-
Це масив структур
CANON_TOOL_TABLE(визначених уsrc/emc/nml_intf/emctool.h), зCANON_POCKETS_MAXзаписами. Індексується за «номером кишені», також відомим як «номером слота». Індекс 0 — це шпиндель, індекси від 1 до (CANON_POCKETS_MAX-1) — це кишені в змінювачі інструментів. У випадковому змінювачі інструментів номери кишень мають значення. У невипадковому змінювачі інструментів кишені не мають значення; номери кишень у файлі таблиці інструментів ігноруються, а інструменти послідовно призначаються слотамtool_table. - settings.tool_change_at_g30
- settings.tool_change_quill_up
- settings.tool_change_with_spindle_on
-
Вони встановлюються з INI-змінних у розділі
[EMCIO]та визначають, як виконуються зміни інструментів.
25. Розрахунок суглобів та осей
25.1. У буфері стану
Буфер стану використовується завданням та інтерфейсами користувача.
ВИПРАВЛЕННЯ: axis_mask та axes надмірно вказують кількість осей
-
status.motion.traj.axis_mask -
Бітова маска з «1» для осей, які присутні, і «0» для осей, які відсутні. X — це біт 0 із значенням 20 = 1, якщо встановлено, Y — це біт 1 із значенням 21 = 2, Z — це біт 2 із значенням 4 тощо. Наприклад, машина з осями X і Z матиме
axis_mask0x5, машина XYZ матиме 0x7, а машина XYZB матимеaxis_mask0x17. -
status.motion.traj.axes(вилучено) -
Це значення було вилучено у версії LinuxCNC 2.9. Замість нього використовуйте
axis_mask. -
status.motion.traj.joints -
Кількість шарнірів, які має верстат. Звичайний токарний верстат має 2 шарніри: один приводить в рух вісь X, а другий — вісь Z. Фрезерний верстат XYYZ має 4 шарніри: один приводить в рух вісь X, один — одну сторону осі Y, другий — іншу сторону осі Y, а третій — вісь Z. Фрезерний верстат XYZA також має 4 шарніри.
-
status.motion.axis[EMCMOT_MAX_AXIS] -
Масив структур осей
EMCMOT_MAX_AXIS.axis[n]є дійсним, якщо(axis_mask & (1 << n))є істинним. Якщо(axis_mask & (1 << n))є хибним, тоaxis[n]не існує на цій машині і його слід ігнорувати. -
status.motion.joint[EMCMOT_MAX_JOINTS] -
Масив структур з’єднань
EMCMOT_MAX_JOINTS.joint[0]доjoint[joints-1]є дійсними, інші не існують на цій машині та мають бути ігноровані.
Наразі в гілці joints-axes все не так, але відхилення від цього дизайну вважаються помилками. Приклад такої помилки можна побачити в обробці осей в src/emc/ini/initraj.cc:loadTraj(). Безсумнівно, їх є більше, і мені потрібна ваша допомога, щоб їх знайти та виправити.
25.2. У русі
Компонент реального часу контролера руху спочатку отримує кількість з’єднань з параметра часу завантаження num_joints. Це визначає, скільки з’єднань HAL-пінів створюється під час запуску.
Кількість суглобів руху можна змінити під час виконання за допомогою команди EMCMOT_SET_NUM_JOINTS з Task.
Контролер руху завжди працює з осями EMCMOT_MAX_AXIS. Він завжди створює дев’ять наборів контактів axis.*.*.