前言
GRBL 是一款高性能、开源的嵌入式 CNC(计算机数控)控制器固件,专为 Arduino 平台优化,广泛应用于雕刻机、激光切割机、3D 打印机及其他精密运动控制场景。自 2009 年发布以来,GRBL 凭借其高效的运动规划算法、稳定的实时控制性能和紧凑的代码结构,成为创客、工程师和制造商的首选解决方案。
本文旨在主要剖析GRBL1.1软件架构,帮助读者理解 GRBL 运动规划。
一.GRBL1.1 模块分类
1.GRBL1.1 文件目录
GRBL的github开源地址:https://github.com/grbl/grbl
以下是基于GRBL1.1文件列出功能表
模块分类 | 头文件(.h) | 源文件(.c) | 主要功能描述 |
---|---|---|---|
核心控制 | coolant_control.h | coolant_control.c | 冷却/波控功能,IO初始化和控制。 |
spindle_control.h | spindle_control.c | 主轴PWM控制及设置。 | |
motion_control.h | motion_control.c | 运动控制流程(直线/圆弧插补、回原、复位等)。 | |
G代码处理 | gcode.h | gcode.c | G代码解析器,遵循rs274/ngc标准,支持手动指令接收。 |
系统配置 | config.h | - | 系统默认宏定义,硬件相关配置(端口、限位、主轴等)。 |
defaults.h | - | 系统命令定义、初始化参数及功能开关。 | |
cpu_map.h | - | 定义不同 CPU 的引脚映射(步进电机、限位开关、主轴 PWM 等)。 | |
settings.h | settings.c | 系统参数及状态通过串口上传至上位机。 | |
存储管理 | eeprom.h | eeprom.c | 全局参数存储,带校验和计算。 |
运动规划 | planner.h | planner.c | 加减速规划(梯形算法、前瞻、拐角限制)。 |
脉冲生成 | stepper.h | stepper.c | 精确脉冲生成(DDA算法等)。 |
限位功能 | limits.h | limits.c | 限位检测与处理(中断调用、权限位管理、回原操作)。 |
通信模块 | serial.h | serial.c | 串口驱动及缓冲区管理。 |
protocol.h | protocol.c | 上位机通信协议解析。 | |
工具与辅助 | nuts_bolts.h | nuts_bolts.c | 基础功能(延时、数学计算、单位转换)。 |
print.h | print.c | 串口字符打印。 | |
系统命令 | system.h | system.c | 系统命令解析(如复位、状态报告)。 |
探针功能 | probe.h | probe.c | 探针相关操作与控制。 |
数据报告 | report.h | report.c | 实时状态反馈(如位置、速度、错误码)、系统诊断信息生成,通过串口上传至上位机。 |
文档与脚本 | - | [doc], [csv], [log] | 项目文档、报警码表格、提交日志。 |
- | [script] | 辅助脚本(Python),用于调试和PWM计算。 | |
- | [markdown] | 说明文档(串口指令、接口等),需用Markdown编辑器阅读。 | |
入口与全局 | - | main.c | 程序入口,预设应用初始化。 |
grbl.h | - | 系统预编译信息汇总(版本、错误提示等)。 |
2.GRBL1.1 思维导图
以下是基于GRBL1.1 主要功能模块画出思维导图
二.GRBL1.1 软件架构
1. 软件架构
以下是 GRBL软件架构流程图
2. 初始化阶段 main() 函数
Grbl 启动时,首先完成硬件和系统状态的初始化:
1.1 外设初始化
- serial_init():初始化串口通信(用于接收G代码指令)。
- stepper_init():配置步进电机控制引脚和定时器(脉冲生成准备)。
- spindle_init() / coolant_init():主轴和冷却液控制初始化。
- limits_init() / probe_init():限位开关和探针功能初始化。
1.2 系统状态重置
- plan_reset() / st_reset():清空运动规划缓冲区和步进电机状态。
- gc_init():初始化G代码解析器,重置坐标偏移和模态状态。
1.3 位置同步
- plan_sync_position() / gc_sync_position():将逻辑坐标与实际机械位置同步(防止开机时位置错乱)。
1.4 进入主循环
- 调用 protocol_main_loop(),开始监听串口指令和实时控制。
3. 主循环运行阶段 protocol_main_loop()
2.1 串口指令处理流程
- 读取指令:serial_read() 从串口缓冲区获取字符,拼接成完整行(如 G1 X100 Y200)。
- 系统命令(如 $ 开头的配置命令):调用 system_execute_line(),修改参数或触发非实时操作(如保存配置到EEPROM)。
- G代码运动命令(如 G0/G1/G2/G3):调用 gc_execute_line(),解析G代码并转换为内部运动指令
2.2 实时控制流程 protocol_execute_realtime()
- 状态监控:检查限位触发、急停信号(sys.abort)。
- 运动控制:处理暂停/恢复(protocol_exec_rt_suspend())、手动进给调整。
- 状态反馈:通过 report.c 实时上传位置、速度、错误码(如 <?> 状态报告)。
2.3 异常处理流程
- 限位触发:limits.c 检测到限位信号 → 触发 sys.abort → 立即停止脉冲生成并上报错误。
- 缓冲区溢出:plan_buffer_line() 检查 block_buffer 剩余空间,若不足则暂停G代码解析。
三.GRBL1.1 数据流
1. GRBL数据流
以下是GRBL 整体数据流图
2. 数据流流程图说明
指令输入:上位机通过串口发送指令,存入缓冲区后分类处理。
G代码解析:圆弧指令(G2/G3)被mc_arc()分解为线段,最终统一由mc_line()处理。
运动规划:plan_buffer_line()计算加减速曲线,缓冲数据后触发执行标志(EXEC_CYCLE_START)。
脉冲生成:定时器中断中通过DDA算法精确控制脉冲时序,实现位置跟踪。
实时响应:动态检测报警(限位/错误)、运动倍率调整、外设状态更新,形成闭环控制。
四.GRBL1.1 运动规划
1. 运动规划数据流
以下是GRBL运动规划数据流图
2. 运动规划结构体
2.1 plan_block_t(运动块结构体)
核心作用:描述单个运动块的几何参数和动力学特性
成员变量 | 类型 | 单位/范围 | 关键说明 |
---|---|---|---|
direction_bits | uint8_t | 位掩码 | 各轴方向标志位(如 X_DIRECTION_BIT ),0=正方向,1=负方向 |
steps[N_AXIS] | uint32_t | 步数 | 每个轴需执行的步进脉冲数(如steps[X_AXIS]) |
step_event_count | uint32_t | 步数 | 总步数基准(取所有轴步数的最大值,决定运动时间) |
entry_speed_sqr | float | (mm/min)² | 实际进入该块时的速度平方(由速度前瞻计算) |
max_entry_speed_sqr | float | (mm/min)² | 允许的最大入口速度(受相邻块约束) |
max_junction_speed_sqr | float | (mm/min)² | 拐角连接点极限速度(基于junction_deviation计算) |
nominal_speed_sqr | float | (mm/min)² | 理论名义速度(受轴最大速度限制) |
acceleration | float | mm/min² | 实际加速度(可能低于全局设置值) |
millimeters | float | mm | 运动路径的几何长度 |
2.2 planner_t(规划器状态结构体)
核心作用:维护规划器的全局状态和历史数据
成员变量 | 类型 | 关键说明 |
---|---|---|
position[N_AXIS] | int32_t | 规划器坐标系下的绝对位置(步数),与G代码解析器独立 |
previous_unit_vec[N_AXIS] | float | 前一个运动块的单位方向向量(用于计算拐角角度) |
previous_nominal_speed_sqr | float | 前一个块的名义速度平方(mm/min)²,用于速度连续性约束 |
2.3 plan_buffer_line();(运动参数传递函数)
核心作用:传递运动参数
参数名 | 类型 | 作用 |
---|---|---|
*target | float[] | 目标位置坐标(绝对毫米坐标,如 {x,y,z}) |
*position | float[] | 起点位置坐标(用于相对模式计算) |
feed_rate | float | 编程进给率(mm/min 或 逆时间模式下的 1/min) |
condition | uint8_t | 运动条件标志位 |
spindle_speed | float | 主轴转速(RPM) |