文档编写:博飞宇智能科技
版本:V1.1
目录#
重要限制#
流程控制语句(IF / WHILE / SUB 等)仅在从文件系统加载的宏程序中可用,不能在交互模式下直接输入使用。
宏文件需放置在文件系统中,通常路径为:
/littlefs/<name>.ngc(LittleFS 文件系统)/<name>.ngc(SD 卡根目录)
1. 表达式语法#
1.1 运算符#
算术运算符#
| 运算符 | 说明 | 示例 |
|---|---|---|
+ |
加法 | [3 + 5] = 8 |
- |
减法 | [10 - 3] = 7 |
* |
乘法 | [4 * 3] = 12 |
/ |
除法 | [10 / 3] = 3.333 |
MOD |
取模 | [10 MOD 3] = 1 |
** |
幂运算 | [2 ** 3] = 8 |
关系运算符(返回 1.0 为真,0.0 为假)#
| 运算符 | 说明 | 示例 |
|---|---|---|
LT |
小于 | [3 LT 5] = 1.0 |
LE |
小于等于 | [5 LE 5] = 1.0 |
EQ |
等于 | [3 EQ 3] = 1.0 |
NE |
不等于 | [3 NE 5] = 1.0 |
GE |
大于等于 | [5 GE 3] = 1.0 |
GT |
大于 | [5 GT 3] = 1.0 |
逻辑运算符#
| 运算符 | 说明 | 示例 |
|---|---|---|
AND |
按位与 | [5 AND 3] = 1 |
OR |
按位或 | [5 OR 3] = 7 |
XOR |
按位异或 | [5 XOR 3] = 6 |
1.2 数学函数#
| 函数 | 说明 | 示例 |
|---|---|---|
ABS[x] |
绝对值 | ABS[-5] = 5 |
ACOS[x] |
反余弦(弧度) | ACOS[1] = 0 |
ASIN[x] |
反正弦(弧度) | ASIN[1] = 1.5708 |
ATAN[x]/[y] |
反正切(弧度) | ATAN[1]/[1] = 0.7854 |
COS[x] |
余弦(弧度) | COS[0] = 1 |
SIN[x] |
正弦(弧度) | SIN[1.5708] = 1 |
TAN[x] |
正切(弧度) | TAN[0.7854] = 1 |
SQRT[x] |
平方根 | SQRT[16] = 4 |
EXP[x] |
e 的 x 次方 | EXP[1] = 2.718 |
LN[x] |
自然对数 | LN[2.718] = 1 |
ROUND[x] |
四舍五入 | ROUND[3.6] = 4 |
FIX[x] |
向零取整 | FIX[-3.6] = -3 |
FUP[x] |
远离零取整 | FUP[-3.2] = -4 |
EXISTS[#<name>] |
参数是否存在 | EXISTS[#<_x>] = 1 |
PRM[x] |
读取设置值 | PRM[100] 读取 $100 设置 |
2. 参数(变量)#
2.1 编号参数#
| 范围 | 说明 | 持久性 |
|---|---|---|
#1 ~ #30 |
子程序局部参数,CALL 时传递 | 调用级局部 |
#31 ~ #5000 |
全局参数 | 断电保持 |
#5001 ~ #5399 |
全局参数 | 断电不保持 |
使用方式#
#100 = 50.0 (设置编号参数)
G0 X#100 (引用编号参数)
#101 = [#100 + 10] (表达式中使用编号参数)
2.2 系统变量(只读,以 _ 开头)#
| 参数 | 说明 |
|---|---|
_x _y _z _a _b _c |
当前相对坐标 |
_abs_x _abs_y _abs_z ... |
当前绝对坐标 |
_feed |
当前进给速率 |
_input0 ~ _input5 |
输入信号状态 |
_motion_mode |
当前运动模式 |
_plane |
当前平面选择 |
_absolute |
是否绝对坐标模式 |
_homed_state |
回零状态 |
_call_level |
当前调用层级 |
_value |
子程序返回值 |
_value_returned |
子程序是否返回了值 |
_free_memory |
剩余内存 |
_line |
当前行号 |
使用方式#
#<pos_x> = #<_abs_x> (读取当前绝对 X 坐标到自定义参数)
#1 = #_input0
O100 IF [#1 EQ 1]
(输入 0 为高电平,执行某操作)
O100 ENDIF
O200 (等待输入 1 变高)
WHILE [#_input1 EQ 0]
G4 P0.1
ENDWHILE
3. 流程控制语句#
所有流程控制语句使用 O 代码格式,语法遵循 LinuxCNC O 代码规范。
O 标签可以是数字或字符串:
- 数字标签:
O100 IF [...]、O200 WHILE [...] - 字符串标签:
O<myloop> WHILE [...]、O<mysub> SUB
3.1 条件判断 IF / ELSEIF / ELSE / ENDIF#
基本用法#
(文件: /littlefs/test_if.macro)
#1 = 10
O100 IF [#1 GT 5]
G0 X50 Y50 (当 #1 > 5 时执行)
O100 ENDIF
IF-ELSE 结构#
#1 = 3
O100 IF [#1 GT 5]
G0 X100 (#1 > 5 时执行)
O100 ELSE
G0 X0 (#1 <= 5 时执行)
O100 ENDIF
IF-ELSEIF-ELSE 链式判断#
#1 = 5
O100 IF [#1 EQ 1]
G0 X10
O100 ELSEIF [#1 EQ 5]
G0 X50 (#1 == 5 时执行此处)
O100 ELSEIF [#1 EQ 10]
G0 X100
O100 ELSE
G0 X0 (以上条件都不满足时执行)
O100 ENDIF
嵌套 IF#
#1 = 10
#2 = 20
O100 IF [#1 GT 5]
O200 IF [#2 GT 15]
G0 X100 Y100 (两个条件都满足时执行)
O200 ELSE
G0 X100 Y0
O200 ENDIF
O100 ELSE
G0 X0 Y0
O100 ENDIF
3.2 WHILE 循环#
基本用法#
(计算 1+2+...+10)
#1 = 0 (累加结果)
#2 = 1 (计数器)
O100 WHILE [#2 LE 10]
#1 = [#1 + #2]
#2 = [#2 + 1]
O100 ENDWHILE
(此时 #1 = 55)
G0 X#1
使用 BREAK 跳出循环#
(查找第一个满足条件的位置)
#1 = 0
O100 WHILE [#1 LE 100]
#1 = [#1 + 1]
O200 IF [#1 ** 2 GT 50]
O100 BREAK (跳出 O100 循环)
O200 ENDIF
O100 ENDWHILE
(此时 #1 = 8,因为 8^2 = 64 > 50)
使用 CONTINUE 跳过本次迭代#
(累加 1-10 中的奇数)
#1 = 0 (累加结果)
#2 = 0 (计数器)
O100 WHILE [#2 LT 10]
#2 = [#2 + 1]
O200 IF [#2 MOD 2 EQ 0]
O100 CONTINUE (偶数跳过)
O200 ENDIF
#1 = [#1 + #2]
O100 ENDWHILE
(此时 #1 = 25 = 1+3+5+7+9)
3.3 DO-WHILE 循环#
先执行循环体,后判断条件(至少执行一次):
(至少执行一次,直到 #1 >= 10)
#1 = 0
O100 DO
G0 X#1
#1 = [#1 + 2]
O100 WHILE [#1 LT 10]
(依次移动到 X0, X2, X4, X6, X8)
3.4 REPEAT 循环#
固定次数重复执行:
(重复钻孔 5 次,每次间距 10mm)
#1 = 0
O100 REPEAT [5]
G0 X#1
G1 Z-5 F100
G0 Z5
#1 = [#1 + 10]
O100 ENDREPEAT
3.5 子程序 SUB / CALL#
定义和调用子程序(数字标签)#
(文件: /littlefs/drill_pattern.macro)
(定义子程序:在当前位置钻孔)
O100 SUB
G1 Z-5 F100 (下钻)
G0 Z5 (抬刀)
O100 ENDSUB
(主程序:在 5 个位置调用子程序)
#1 = 0
O200 REPEAT [5]
G0 X#1 Y0
O100 CALL (调用子程序 O100)
#1 = [#1 + 10]
O200 ENDREPEAT
子程序传参(位置参数 #1 - #30)#
(文件: /littlefs/drill_at.macro)
(定义带参数的子程序:在指定位置钻孔)
O100 SUB
G0 X#1 Y#2 (移动到 #1=X, #2=Y 指定的位置)
G1 Z#3 F100 (下钻深度由 #3 指定)
G0 Z5
O100 ENDSUB
(主程序:在不同位置和深度钻孔)
O100 CALL [10] [20] [-5] (在 X10 Y20 钻深 5)
O100 CALL [30] [40] [-8] (在 X30 Y40 钻深 8)
O100 CALL [50] [10] [-3] (在 X50 Y10 钻深 3)
子程序返回值#
(文件: /littlefs/calc_area.macro)
(定义计算面积的子程序)
O100 SUB
#10 = [#1 * #2] (长 * 宽)
O100 ENDSUB [#10] (返回面积值)
(主程序)
O100 CALL [5] [3] (计算 5x3 的面积)
#<area> = #<_value> (读取返回值到命名参数)
(此时 #<area> = 15.0,#<_value_returned> = 1.0)
命名子程序(从 .ngc 文件加载)#
命名子程序以字符串标签标识,系统会自动从文件系统加载对应的 .ngc 文件。
(文件: /littlefs/drill_slot.ngc)
(调用命名子程序,系统自动加载 /littlefs/safe_drill.ngc)
O<safe_drill> CALL [50] [30] [-10]
对应的子程序文件 /littlefs/safe_drill.ngc:
(安全钻孔子程序)
(参数: #1=X, #2=Y, #3=深度)
G0 Z5 (先抬刀到安全高度)
G0 X#1 Y#2 (快速移动到目标位置)
G1 Z#3 F80 (慢速下钻)
G0 Z5 (抬刀返回安全高度)
3.6 RETURN 语句#
从子程序中提前返回:
O100 SUB
O200 IF [#1 LT 0]
O100 RETURN (参数无效,提前返回)
O200 ENDIF
G0 X#1
O100 ENDSUB
3.7 触发报警或错误#
(参数越界时触发报警)
O100 IF [#1 LT 0]
O100 ALARM [1] (触发报警码 1)
O100 ENDIF
(严重错误时触发错误码)
O200 IF [#2 EQ 0]
O200 ERROR [80] (触发错误码 80)
O200 ENDIF
3.8 读取机器状态#
G65 P4 (获取机器状态)
#<state> = #<_value> (读取返回值)
(状态值: 0=空闲, 1=报警, 2=检查模式, 3=回零中, 4=运行中, 5=暂停, 6=点动, 7=未知, 8=休眠, 9=急停)
O100 IF [#<state> EQ 4.0]
MSG,机器正在运行中
O100 ELSEIF [#<state> EQ 9.0]
O100 ALARM [1] (急停状态,触发报警)
O100 ELSEIF [#<state> EQ 0.0]
MSG,机器空闲
O100 ENDIF
3.9 检查轴是否回零#
(检查 Z 轴是否已回零,Z_AXIS = 4)
#<homed_mask> = #<_homed_axes>
#<z_homed> = [#<homed_mask> AND 4]
O100 IF [#<z_homed> EQ 4.0]
G0 Z5 (Z 轴已回零)
O100 ELSE
O100 ALARM [9] (Z 轴未回零,报警)
O100 ENDIF
4. 注意事项#
文件系统依赖:流程控制语句必须从文件系统(LittleFS 或 SD 卡)加载的
.ngc文件中执行,串口或网口直接输入不支持。栈深度限制:嵌套层级最大为 20 层,包括嵌套的 IF、WHILE、CALL 等。超出会触发
Status_FlowControlStackOverflow错误。参数数量限制:CALL 传递的位置参数最多 30 个(
#1~#30)。内存限制:WHILE 循环的表达式需要动态分配内存保存,子程序信息也需要
malloc。内存不足时会触发Status_FlowControlOutOfMemory错误。O 标签匹配:每个流程控制块的开始和结束必须使用相同的 O 标签,例如
O100 IF必须对应O100 ENDIF,否则会报语法错误。表达式中的方括号:表达式必须用
[]包裹,如[3 + 5],不支持()。嵌套表达式也用[],如[[3 + 5] * 2]。浮点比较:条件判断中
EQ(等于)对浮点数可能不精确,建议使用范围判断,如[ABS[#1 - #2] LT 0.001]代替[#1 EQ #2]。注释中的 ABORT:在注释中使用
(ABORT,消息内容)可以在流程控制中触发用户异常,中断执行并显示消息。
文档编写:博飞宇智能科技
版本:V1.1