Files
cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/doc/AXIS主控制按钮功能先决条件与状态影响详解.md
2026-07-07 09:40:33 -04:00

704 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AXIS 主控制按钮功能、先决条件与机床状态影响详解
本文档单独整理 `5axis-xyzbc-trt-sim` 配置在 AXIS 界面中常用主控制按钮的执行条件、状态影响和对应程序链路。目标配置为:
```text
configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
```
该配置使用:
- GUI`[DISPLAY] DISPLAY = axis`
- 任务进程:`[TASK] TASK = milltask`
- HAL 仿真闭环:`[HAL] HALFILE = LIB:basic_sim.tcl`
- 默认打开程序:`[DISPLAY] OPEN_FILE = ./demos/xyzbc_switchkins.ngc`
- 运动学:`[KINS] KINEMATICS = xyzbc-trt-kins sparm=identityfirst`
- 关节数:`[KINS] JOINTS = 5`
## 1. 状态和模式基础
AXIS 主按钮最终通过 Python `linuxcnc.command()` 对象发送 NML 命令给 `milltask`。常见状态如下:
| 名称 | LinuxCNC 常量 | 含义 |
|---|---|---|
| 急停中 | `STATE_ESTOP` | 急停有效,机床关闭,运动禁止 |
| 急停已解除但未上电 | `STATE_ESTOP_RESET` | 急停链释放,机床仍未使能 |
| 下电 | `STATE_OFF` | 机床未使能Python 扩展说明中等价于急停复位后的 off 状态 |
| 上电 | `STATE_ON` | 急停释放且机床使能可回零、MDI、自动运行 |
常见任务模式如下:
| 名称 | LinuxCNC 常量 | 用途 |
|---|---|---|
| 手动 | `MODE_MANUAL` | 回零、点动、手动操作 |
| MDI | `MODE_MDI` | 执行单行 MDI 指令 |
| 自动 | `MODE_AUTO` | 执行已装载 G-code 程序 |
核心源码位置:
```text
src/emc/usr_intf/axis/scripts/axis.py
src/emc/usr_intf/axis/extensions/emcmodule.cc
src/emc/task/emctaskmain.cc
src/emc/task/emctask.cc
src/emc/task/taskintf.cc
src/emc/nml_intf/emc_nml.hh
```
## 2. 按钮总表
| 按钮/动作 | AXIS 回调函数 | Python API | NML 命令 | 主要先决条件 | 主要状态影响 |
|---|---|---|---|---|---|
| 急停 | `estop_clicked()` | `c.state(STATE_ESTOP)` | `EMC_TASK_SET_STATE` | LinuxCNC 已运行;通常任意非急停状态都可触发 | 中止运动、主轴、冷却;使能关闭;进入 `STATE_ESTOP` |
| 解除急停 | `estop_clicked()` | `c.state(STATE_ESTOP_RESET)` | `EMC_TASK_SET_STATE` | 当前为 `STATE_ESTOP` | 释放急停链;仍未上电;进入 `STATE_ESTOP_RESET` |
| 上电 | `onoff_clicked()` | `c.state(STATE_ON)` | `EMC_TASK_SET_STATE` | 当前为 `STATE_ESTOP_RESET` | 轨迹/运动使能;进入 `STATE_ON` |
| Home | `home_all_joints()` / `home_joint()` | `c.home(joint)` | `EMC_JOINT_HOME` | `STATE_ON`;解释器空闲;手动模式;没有正在回零的关节 | 指定关节或全部关节回零,`homed[]` 变为 true |
| 执行程序 | `task_run()` | `c.auto(AUTO_RUN, line)` | `EMC_TASK_PLAN_RUN` | 上电、已回零、程序已打开、通过运行前检查 | 切入自动模式,解释器进入 `READING`,开始运行 G-code |
| 暂停 | `task_pause()` | `c.auto(AUTO_PAUSE)` | `EMC_TASK_PLAN_PAUSE` | 自动模式;解释器处于 `READING``WAITING` | 轨迹暂停,解释器状态保存为 `PAUSED``task_paused=1` |
| 恢复暂停 | `task_resume()` / `task_pauseresume()` | `c.auto(AUTO_RESUME)` | `EMC_TASK_PLAN_RESUME` | 当前已暂停;自动或 MDI 模式;未被 `resume-inhibit` 禁止 | 轨迹恢复,解释器返回暂停前状态,`task_paused=0` |
| 单步执行 | `task_step()` | `c.auto(AUTO_STEP)` | `EMC_TASK_PLAN_STEP` | 自动模式且解释器空闲;若不是空闲会先做运行警告检查 | 打开 single step一次推进一个解释/运动步骤 |
## 3. 急停
### 3.1 执行入口
AXIS 中急停按钮和 `F1` 键使用同一个回调:
```python
def estop_clicked(event=None):
s.poll()
if s.task_state == linuxcnc.STATE_ESTOP:
c.state(linuxcnc.STATE_ESTOP_RESET)
else:
c.state(linuxcnc.STATE_ESTOP)
```
按下时如果当前不是 `STATE_ESTOP`,就是执行急停;如果当前已经是 `STATE_ESTOP`,就是解除急停。
### 3.2 先决条件
- LinuxCNC 已启动AXIS 可读取状态并可向 command channel 发送命令。
- 不要求当前在手动、MDI 或自动模式。
- 不要求程序空闲;急停是最高优先级安全动作,可在运动中触发。
### 3.3 机床状态影响
急停发送:
```text
c.state(linuxcnc.STATE_ESTOP)
```
Python 扩展生成:
```text
EMC_TASK_SET_STATE(state = ESTOP)
```
`milltask` 调用:
```text
emcTaskSetState(EMC_TASK_STATE::ESTOP)
```
主要影响:
- `emcMotionAbort()`:立即中止当前运动。
- `emcSpindleAbort()`:中止主轴。
- `emcAuxEstopOn()`:置 IO 急停。
- `emcTrajDisable()`:关闭轨迹/运动使能。
- `emcCoolantFloodOff()`:关闭冷却。
- `emcTaskAbort()`:中止任务层正在执行的程序/MDI。
- `emcIoAbort(TASK_STATE_ESTOP)`:通知 IO 层急停原因。
- `emcJointUnhome(-2)`:仅清除配置为 volatile home 的关节回零状态。
- `emcTaskPlanSynch()`:同步解释器/任务计划状态。
在本仿真配置中,`basic_sim.tcl``motion.motion-enabled` 接到仿真伺服闭环选择信号。急停后 motion disabled仿真反馈保持当前位置不再跟随新的 `joint.N.motor-pos-cmd`
## 4. 解除急停
### 4.1 执行入口
仍然是 AXIS 的 `estop_clicked()`。当前状态为 `STATE_ESTOP` 时,按钮执行:
```text
c.state(linuxcnc.STATE_ESTOP_RESET)
```
### 4.2 先决条件
- 当前必须处于 `STATE_ESTOP`,否则同一个按钮会变成“急停”动作。
- 外部急停链、HAL 急停反馈需要允许复位。本仿真中 `basic_sim.tcl` 使用回环:
```text
iocontrol.0.user-enable-out -> iocontrol.0.emc-enable-in
```
所以没有真实硬件急停链阻塞。
### 4.3 机床状态影响
`emcTaskSetState(ESTOP_RESET)` 主要执行:
- `emcAuxEstopOff()`:释放急停。
- `emcCoolantFloodOff()`:保持冷却关闭。
- `emcTaskAbort()`:清理任务执行状态。
- `emcIoAbort(TASK_STATE_ESTOP_RESET)`:通知 IO 层状态变化。
- `emcSpindleAbort()`:确保主轴停止。
- `emcAbortCleanup()`:清理 abort 状态。
- `emcTaskPlanSynch()`:同步解释器。
解除急停后机床仍然没有上电,状态是:
```text
STATE_ESTOP_RESET
```
此时不能执行 Home、MDI 或自动运行,需要再按“上电”。
## 5. 上电
### 5.1 执行入口
AXIS 中上电/下电按钮和 `F2` 键使用:
```python
def onoff_clicked(event=None):
s.poll()
if s.task_state == linuxcnc.STATE_ESTOP_RESET:
c.state(linuxcnc.STATE_ON)
...
else:
c.state(linuxcnc.STATE_OFF)
```
因此该按钮也是切换按钮:当前为 `STATE_ESTOP_RESET` 时执行上电;否则执行下电。
### 5.2 先决条件
- 必须先解除急停,当前状态为 `STATE_ESTOP_RESET`
- 如果当前仍为 `STATE_ESTOP`,点击该按钮不会上电,而会进入 `STATE_OFF` 分支,实际无法达到可运动状态。
### 5.3 机床状态影响
上电发送:
```text
c.state(linuxcnc.STATE_ON)
```
`emcTaskSetState(ON)` 主要执行:
- `emcTrajEnable()`:向实时 motion 发送 `EMCMOT_ENABLE`
- `emcCoolantFloodOff()`:确保冷却默认关闭。
上电后:
- `task_state = STATE_ON`
- 运动系统使能。
- `motion.motion-enabled` 为真。
- 本仿真 HAL 中各关节 PID pass-through 被允许,`joint.N.motor-pos-cmd` 可通过仿真闭环更新到 `joint.N.motor-pos-fb`
### 5.4 下电补充
如果机器已经不是 `STATE_ESTOP_RESET`,同一个按钮会发送:
```text
c.state(linuxcnc.STATE_OFF)
```
下电影响包括中止运动、关闭轨迹使能、通知 IO、清理任务、同步解释器并清除 volatile home 关节的回零状态。
## 6. Home
### 6.1 执行入口
本配置 5 个关节都设置了:
```ini
HOME_SEARCH_VEL = 0
HOME_SEQUENCE = 0
```
AXIS 会显示 `Home All` 按钮。按钮执行:
```python
def home_all_joints(event=None):
if not manual_ok(): return
ensure_mode(linuxcnc.MODE_MANUAL)
...
go_home(-1)
```
`Home` 键可执行当前选择关节的 `home_joint()``Ctrl-Home` 执行全部回零。
`go_home()` 内部执行:
```python
set_motion_teleop(0)
c.home(num)
c.wait_complete()
```
其中 `num = -1` 表示全部关节。
### 6.2 先决条件
Home All 的主要条件:
- `manual_ok()` 为真:
- `task_state == STATE_ON`
- 解释器空闲,或者 MDI 队列仍允许用户动作
- AXIS 会切换到 `MODE_MANUAL`
- 当前没有任何关节正在回零;`go_home()` 会检查 `s.joint[j]["homing"]`
- 如果已经全部回零AXIS 会弹出确认提示。
单个关节 Home 的额外条件:
- 如果选择的是坐标轴字母,并且当前运动学不是 identityAXIS 会提示使用 joint mode 回零并拒绝直接按轴回零。
- 对重复坐标字母配置AXIS 禁止按轴单独回零。
本配置启动默认是 `sparm=identityfirst`,即 `switchkins-type = 0` 为 identity适合先回零。
### 6.3 机床状态影响
Home 发送:
```text
c.home(joint)
```
Python 扩展生成:
```text
EMC_JOINT_HOME(joint = -1 或具体关节号)
```
`milltask` 调用:
```text
emcJointHome(joint)
```
`taskintf.cc` 再向实时 motion 发送:
```text
EMCMOT_JOINT_HOME
```
本仿真使用 `basic_sim.tcl``simulated_home`,为每个关节建立:
```text
joint.N.home-sw-in
```
由于 `HOME_SEARCH_VEL = 0`,这是仿真中的立即/简化回零方式。完成后:
- 对应 `s.homed[N]` 变为 true。
- `Home All` 后 5 个关节均为已回零。
- 只有已回零后,普通配置才允许自动运行程序;`emctaskmain.cc``EMC_TASK_PLAN_RUN` 会检查 `all_homed()`
## 7. 执行程序
### 7.1 执行入口
AXIS 运行按钮和 `r` 键执行:
```python
def task_run(*event):
res = run_warn()
...
ensure_mode(linuxcnc.MODE_AUTO)
c.auto(linuxcnc.AUTO_RUN, program_start_line)
```
当前配置启动时自动打开:
```text
configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc
```
该文件内容很短:
```ngc
o<xyzbc_switchkins_sub> call [10] [5] [10][1000][3][0][20][45][20]
m2
```
实际加工/演示逻辑在:
```text
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/xyzbc_switchkins_sub.ngc
configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/helix_bc.ngc
```
### 7.2 先决条件
AXIS 层:
- 程序已经打开。
- `run_warn()` 运行前检查通过,或用户选择忽略软限位警告继续运行。
- AXIS 能切换到 `MODE_AUTO`
任务层:
- 机床需要处于可运行状态,通常为 `STATE_ON`
- 必须已经回零,除非配置关闭强制回零。`emctaskmain.cc``EMC_TASK_PLAN_RUN` 检查:
```text
if (!all_homed() && !no_force_homing) {
"Can't run a program when not homed"
}
```
### 7.3 机床状态影响
运行按钮发送:
```text
c.auto(linuxcnc.AUTO_RUN, program_start_line)
```
Python 扩展生成:
```text
EMC_TASK_PLAN_RUN(line = program_start_line)
```
任务层影响:
- 清除 single stepping
- `motion.traj.single_stepping = 0`
- `stepping = 0`
- 如果 task plan 尚未打开且有文件名,则打开当前 G-code 文件。
- 设置 `programStartLine`
- 设置解释器状态:
```text
interpState = READING
task_paused = 0
```
之后解释器读取 G-code生成 canonical commands`taskintf` 下发给 realtime motionmotion 在伺服周期中计算轨迹和各 joint 命令。
### 7.4 对当前演示程序的影响
`xyzbc_switchkins_sub.ngc` 会在四个象限重复执行:
1. `M429` 切换到 identity。
2. `G53 G0 X0 Y0 Z... B0 C0` 回到机床坐标安全姿态。
3. `G10 L20 P0 ...` 设置 G54。
4. 移动到当前象限中心。
5. 调用 `helix_bc` 执行带 B/C 姿态的螺旋轨迹。
其中 `M428/M429/M430` 是 remap
- `M429``motion.switchkins-type = 0`identity。
- `M428``motion.switchkins-type = 1`xyzbc TRT。
- `M430``motion.switchkins-type = 2`userk。
remap 通过:
```ngc
M68 E3 Q#<kinstype>
M66 E0 L0
```
把数值写入 `motion.analog-out-03`,再由 INI 中 HAL 网络连接到:
```text
motion.switchkins-type
```
## 8. 暂停
### 8.1 执行入口
AXIS 暂停按钮和 `p` 键执行:
```python
def task_pause(*event):
if s.task_mode != linuxcnc.MODE_AUTO or \
s.interp_state not in (linuxcnc.INTERP_READING, linuxcnc.INTERP_WAITING):
return
ensure_mode(linuxcnc.MODE_AUTO)
c.auto(linuxcnc.AUTO_PAUSE)
```
### 8.2 先决条件
- 当前必须在 `MODE_AUTO`
- 解释器状态必须是:
- `INTERP_READING`:正在读程序
- `INTERP_WAITING`:等待运动或 IO 完成
- 如果程序已经空闲、已经暂停、处于手动或 MDIAXIS 直接返回,不发送暂停命令。
### 8.3 机床状态影响
暂停发送:
```text
EMC_TASK_PLAN_PAUSE
```
任务层执行:
```text
emcTrajPause()
interpResumeState = 当前解释器状态
interpState = PAUSED
task_paused = 1
```
效果:
- 轨迹规划暂停。
- 已进入 motion 队列的运动按 LinuxCNC pause 逻辑停止/保持。
- AXIS 状态显示为 paused。
- 后续恢复会回到 `interpResumeState`
## 9. 恢复暂停
### 9.1 执行入口
AXIS 恢复按钮和 `s` 键执行:
```python
def task_resume(*event):
s.poll()
if not s.paused:
return
if s.task_mode not in (linuxcnc.MODE_AUTO, linuxcnc.MODE_MDI):
return
ensure_mode(linuxcnc.MODE_AUTO, linuxcnc.MODE_MDI)
c.auto(linuxcnc.AUTO_RESUME)
```
AXIS 的暂停/恢复合并按钮 `task_pauseresume()` 还会检查:
```text
resume-inhibit
```
如果该 HAL pin 为真,则禁止恢复。本配置中 AXIS 创建了 `axisui.resume-inhibit` 输入 pin`xyzbc-trt.ini` 没有把它接到其他信号,默认不阻塞恢复。
### 9.2 先决条件
- 当前必须已经暂停,即 `s.paused` 为真。
- 当前模式必须是 `MODE_AUTO``MODE_MDI`
- 对合并暂停/恢复按钮,`resume-inhibit` 不能为真。
### 9.3 机床状态影响
恢复发送:
```text
EMC_TASK_PLAN_RESUME
```
任务层执行:
```text
emcTrajResume()
interpState = interpResumeState
task_paused = 0
motion.traj.single_stepping = 0
stepping = 0
steppingWait = 0
```
效果:
- 轨迹恢复。
- 解释器继续从暂停点运行。
- 关闭单步状态,回到连续运行。
## 10. 单步执行
### 10.1 执行入口
AXIS 单步按钮和 `t` 键执行:
```python
def task_step(*event):
if s.task_mode != linuxcnc.MODE_AUTO or s.interp_state != linuxcnc.INTERP_IDLE:
o.set_highlight_line(None)
if run_warn(): return
ensure_mode(linuxcnc.MODE_AUTO)
c.auto(linuxcnc.AUTO_STEP)
```
### 10.2 先决条件
常见使用方式:
- 机床上电。
- 已回零。
- 程序已打开。
- 当前可切换到 `MODE_AUTO`
- 如果不是自动空闲状态AXIS 会先清除高亮并执行 `run_warn()` 检查;如果用户取消或检查失败,则不单步。
任务层对第一次单步有特殊处理:
- 如果自动模式空闲时收到 `EMC_TASK_PLAN_STEP`,会先发起从第 0 行运行,再立即暂停轨迹,使程序进入单步逻辑。
### 10.3 机床状态影响
单步发送:
```text
EMC_TASK_PLAN_STEP
```
任务层按当前执行阶段处理:
- 在自动空闲初次单步时:
- 创建 `EMC_TASK_PLAN_RUN(line=0)`
- 执行 run
- 调用 `emcTrajPause()`
- 在解释器读取/等待/暂停过程中:
- `motion.traj.single_stepping = 1`
- `stepping = 1`
- `steppingWait = 0`
- 如果轨迹队列已有暂停运动,单步会推进队列中的下一步
效果:
- 每次点击只推进一个解释/运动步骤。
- 与“恢复暂停”不同,单步不会切回连续运行。
- 恢复暂停会清除 single stepping。
## 11. 当前 5 轴仿真配置的特殊注意点
### 11.1 启动默认不能直接运行
启动后通常处于急停或未上电状态。正确顺序是:
```text
解除急停 -> 上电 -> Home All -> 执行程序
```
如果未回零直接执行程序,任务层会报:
```text
Can't run a program when not homed
```
### 11.2 Home 与 switchkins 的关系
本配置 `sparm=identityfirst`,启动默认:
```text
motion.switchkins-type = 0
```
也就是 identity kinematics。回零应优先在 identity 下完成。演示程序内部也会反复使用 `M429` 回到 identity 后再做安全定位和坐标设置。
### 11.3 执行程序与 PyVCP 运动学按钮的关系
主运行按钮执行当前打开的 G-code。右侧 PyVCP 的:
- `IDENTITY`
- `TCP:XYZBC`
- `userk`
不是主运行控制按钮,它们通过 `switchkins_postgui.hal` 接到:
```text
halui.mdi-command-00 -> M429
halui.mdi-command-01 -> M428
halui.mdi-command-02 -> M430
```
这些按钮本质是发送 MDI 命令切换运动学,不负责运行、暂停或恢复程序。
### 11.4 仿真 HAL 对状态的响应
`basic_sim.tcl` 建立的关键闭环:
```text
iocontrol.0.user-enable-out -> iocontrol.0.emc-enable-in
motion.motion-enabled -> JN_mux.sel
joint.N.amp-enable-out -> JN_pid.enable
joint.N.motor-pos-cmd -> JN_pid.command
JN_pid.output -> JN_mux.in1
JN_mux.out -> joint.N.motor-pos-fb
```
因此:
- 急停/下电会关闭 motion enable反馈保持不继续跟随命令。
- 上电后 motion enable 打开,仿真伺服闭环重新允许命令传递到反馈。
- Home 通过 `sim_home_switch` 给每个 `joint.N.home-sw-in` 提供模拟 home switch。
## 12. 推荐操作流程
启动:
```bash
cd /home/mes123456/linuxcnc-master
scripts/rip-environment linuxcnc configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini
```
标准执行顺序:
```text
1. 点击急停按钮或 F1解除急停使状态到 STATE_ESTOP_RESET。
2. 点击上电按钮或 F2进入 STATE_ON。
3. 点击 Home All 或 Ctrl-Home5 个关节全部回零。
4. 确认已打开 demos/xyzbc_switchkins.ngc。
5. 点击 Run 或按 r进入 MODE_AUTO 并执行程序。
6. 需要临时停止时按 Pause 或 p。
7. 需要继续时按 Resume 或 s。
8. 需要逐步观察时按 Step 或 t。
9. 任何异常情况下按 F1 急停。
```
## 13. 对应程序链路汇总
### 13.1 急停、解除急停、上电
```text
AXIS 按钮/F1/F2
-> axis.py estop_clicked() / onoff_clicked()
-> linuxcnc.command().state(...)
-> emcmodule.cc state()
-> EMC_TASK_SET_STATE
-> emctaskmain.cc emcTaskIssueCommand()
-> emctask.cc emcTaskSetState()
-> taskintf.cc emcTrajEnable/Disable, emcMotionAbort
-> realtime motion / IO / HAL 状态变化
```
### 13.2 Home
```text
AXIS Home All / Home Joint / Ctrl-Home / Home
-> axis.py home_all_joints() / home_joint()
-> go_home()
-> linuxcnc.command().home(...)
-> emcmodule.cc home()
-> EMC_JOINT_HOME
-> emctaskmain.cc emcJointHome()
-> taskintf.cc EMCMOT_JOINT_HOME
-> realtime motion homing
-> basic_sim.tcl simulated_home / sim_home_switch
-> joint.N.homed = true
```
### 13.3 运行、暂停、恢复、单步
```text
AXIS Run/Pause/Resume/Step
-> axis.py task_run/task_pause/task_resume/task_step
-> linuxcnc.command().auto(...)
-> emcmodule.cc emcauto()
-> EMC_TASK_PLAN_RUN / PAUSE / RESUME / STEP
-> emctaskmain.cc
-> RS274NGC interpreter / task planner / trajectory planner
-> realtime motion
-> HAL 仿真闭环
-> Vismach 与 AXIS 状态显示
```