Skip to content

grbl

tested on simulator

Tier Tier 2
Protocol GRBL 1.1 over USB serial
Covers desktop CNC routers, diode and CO2 laser engravers, pen plotters
Hazard default high
Conformance full
Tested with GRBL 1.1 line protocol simulator over a simulated serial port and a real pty

Estimated reach. Hundreds of machine models, most hobby CNC routers and diode lasers. GRBL is the default firmware on Arduino based CNC shields and on most budget CNC routers and diode laser engravers. Many 32-bit controllers run grblHAL, which keeps the same 1.1 line protocol, so the driver covers them as well. The count is a model estimate, not a unit count.

The grbl driver controls CNC routers, laser engravers and plotters running GRBL 1.1 or grblHAL over USB serial. describe() builds channels from $$.

Supports

Channel nameKindGRBL source
stateread, enum idle run hold jog alarm door check home sleepstatus report ?
alarmread, dimensionlessthe last ALARM:N, 0 when not in alarm
position_x, position_y, position_z, position_aread, lengthmachine position, MPos
work_x, work_y, work_z, work_aread, lengthwork position, WPos
feed_rateread, mm/min or any speed unitFS or F
pinsread, stringPn, such as XP
spindle_speedset, rpmM3 S<rpm>, M5 at 0
laser_powerset, percentM4 S<percent x $30 / 100>, M5 at 0
flood, mistset, boolM8, M7, M9
homeaction$H
jog with x, y, z, a, feedaction$J=G21 G91 ...
move with x, y, z, a, feedactionG21 G90 G1 ...
set_work_zero with axesactionG10 L20 P0 X0 ...
cancel_jog, hold, resume, resetactionrealtime 0x85, !, ~, 0x18
clear_alarmaction$X

Other names need a map.

MapMeaning
{ status: x, frame: work }One status field, state, alarm, x, y, z, a, feed, spindle or pins
{ setting: 130 }Any numeric $ setting, read-only, in the setting's unit
{ spindle: ccw }Spindle with M4 instead of M3
{ laser: constant }Laser with M3 instead of M4
{ coolant: mist }Coolant output flood or mist
{ command: move, distance: relative, frame: machine, rapid: true }An action under another name. move defaults to absolute work coordinates and G1

Lengths go out in mm with G21 on every line, and inch reports convert back. No raw G-code action exists, since a raw line would bypass the file's limits.

How the protocol is handled

  • Each line goes out after the previous ok or error:N, and error numbers become sentences.
  • Reads within status_age share one ? status report.
  • jog, move and home return done once the machine is idle, or started after action_wait.
  • ALARM:N fails the command in flight, and after a limit alarm only a reset goes through. A Grbl 1.1h banner means the board reset and fails commands in flight.

Safe state

A stop sends feed hold, allows 2 s, then sends a Ctrl-X soft reset that turns off the spindle, laser and coolant. A machine stopped mid-move comes back in ALARM:3, so home or clear the alarm before the next job. The file's safe state steps run afterwards, and an output already off in $G counts as done.

Setup

Install with uv tool install --compile-bytecode "halkit[grbl] @ git+https://github.com/sohan-bhat/OpenHAL", close any sender holding the port such as UGS, Candle, LightBurn or bCNC, and start from openhal/drivers/grbl/examples/3018-router.hal.yaml.

KeyDefaultMeaning
portrequiredDevice path, pyserial URL or auto with match.usb
baud115200Baud rate
timeout5 sDeadline for ok or a status report
settle2 sLongest banner delay after opening
action_wait8 sTime before motion actions return started, at most 9 s
status_age200 msStatus report reuse window

Known limitations

  • No G-code streaming. Run jobs from a sender and use the driver to watch, hold and stop.
  • No overrides yet, and only the active work coordinate system.
  • In laser mode M4 fires only while moving. { laser: constant } uses M3, which stays on.
  • Spindle speeds outside $31 to $30 are blocked, since GRBL would clamp the speed silently.

Hazard defaults

high, so the hub holds every change and action until a person approves the request. Keep a physical e-stop that cuts motor and spindle power.

Sources