Skip to content

grblHAL Module

The grblhal_module is the dedicated UI integration layer for the grblHAL CNC firmware. It lives under main/display/cnc/grblhal/ and provides all screen logic, components, and protocol handling that are specific to grblHAL — as opposed to the shared CNC infrastructure in cnc_shared or the firmware-agnostic screens in common_screens.

grblHAL is an advanced real-time CNC motion controller with features that require specialized UI handling:

  • A manual tool change protocol based on grblHAL-specific realtime bytes (0xA3) and firmware states (TOOL)
  • A flat SD card file listing via $F (recursive, full paths, no directory markers)
  • A PASSIVE connection mode (R status) where the remote session has read-only access because another client holds the control token
  • Extended axis naming configurable via $376 (UVW renaming scheme)
  • Probe-disconnected detection via |Pn:O in status reports

This module mirrors the structure of the grbl_module and fluidnc_module, each implementing firmware-specific screen variants on top of the shared cnc_shared infrastructure and the common UI framework.


Core Platform

Shared CNC (cnc_shared)

grblHAL Module (main/display/cnc/grblhal/)

dispatches to

dispatches to

dispatches to

dispatches to

dispatches to

dispatches to

dispatches to

dispatches to

subscribes

subscribes

subscribes

sendGcode

sendGcode

sendGcode

reads

calls

Common Screens

input_screen

message_box_screen

splash_screen

Screen Router

esp3d_screen_type.cpp

createScreen()

Connection Status Component

components/connection_status.h

Change Tool Screen

screens/change_tool_screen.cpp

Files Screen

screens/files_screen.cpp

Probe Screen

screens/probe_screen.cpp

main_screen

jog_screen

status_screen

macros_screen

settings_screen / settings_list_screen

information_screen

FirmwareStatusComponent

ESP3DValues

(event bus)

esp3d_gcode_handler_service

(grblHAL target)

UIManager


The module is organized into five distinct sub-components:

Sub-moduleFileResponsibility
Screen Routerscreens/esp3d_screen_type.cppCentral createScreen() dispatcher for all screen types
Connection Statuscomponents/connection_status.hClickable connection indicator with grblHAL PASSIVE state support
Change Tool Screenscreens/change_tool_screen.cppM6 / M61Q tool change with full grblHAL protocol state machine
Files Screenscreens/files_screen.cppSD card browser using grblHAL’s flat $F listing
Probe Screenscreens/probe_screen.cppMulti-step G38.2 probe sequence with offset application

probe prompt

result returned

run file

confirm/delete

return

numeric input

return

numeric input

return

main_screen

jog_screen

status_screen

settings_screen

files_screen ★

macros_screen

settings_list_screen

information_screen

change_tool_screen ★

probe_screen ★

message_box_screen

input_screen

★ = grblHAL-specific screens. All other screens are shared via cnc_shared or common_screens.


File: main/display/cnc/grblhal/screens/esp3d_screen_type.cpp
Detailed docs: grblhal_module_screen_router.md

The module’s single createScreen(ESP3DScreenType) function is the sole entry point for all screen transitions within the grblHAL firmware target. It is called by all timer-based transition callbacks system-wide.

Key behaviors:

  • Dispatches to mainScreen::create(), filesScreen::create(), probeScreen::create(), changeToolScreen::create(), and all shared screens
  • Conditionally compiles transport-specific screens (scan_bt, wifi_scan, server_scan, output_selection) based on build flags
  • Falls back to mainScreen::create() on unknown screen types
  • Handles the connection_status screen with a pre-configured return target of ESP3DScreenType::settings

File: main/display/cnc/grblhal/components/connection_status.h
Detailed docs: grblhal_module_connection_status.md

The ConnectionStatusComponent is a clickable overlay widget displayed on all grblHAL CNC screens. It renders a connection icon that reflects the current transport and server state, and navigates to connection_status_screen on click.

grblHAL-specific connection states:

Status CharMeaning
?Disconnected / not connected
AAuthentication failed
TConnecting (transport or server handshake in progress)
CConnected — full control
RConnected — read-only (grblHAL PASSIVE: token held by another client)
.Radio off

The R (PASSIVE) state is unique to grblHAL: it signals that another client currently holds the control token, making the pendant read-only. This state is absent from the grbl and fluidnc variants.

initial

transport start

server ack

bad credentials

grblHAL PASSIVE\n(token held by other client)

token released

link lost

retry

Disconnected

Connecting

Connected

AuthFailed

ReadOnly


File: main/display/cnc/grblhal/screens/change_tool_screen.cpp
Detailed docs: grblhal_module_change_tool.md

The change tool screen implements grblHAL’s manual tool change protocol (T<n> M6) and the instant set-current-tool command (M61Q<n>). It exposes a two-item panel (mode toggle + target tool selector) and a virtual 3-button bar that adapts dynamically to the current protocol state.

ModeCommandDescription
SET (default)M61Q<n>Sets current tool number without movement (instant)
CHANGET<n> M6Full grblHAL manual tool change: machine moves to change position, user installs tool, then resumes

grblHAL Tool Change Protocol State Machine

Section titled “grblHAL Tool Change Protocol State Machine”

T&<n&> M6 sent\n(CHANGE mode)

M61Q&<n&> sent\n(SET mode)

firmware enters\n"TOOL" state

user sends 0xA3 ack

user requests $TPW\n(tool setter probe)

user sends ~ (cycle start)

$TPW probe done\n(TOOL state re-entered)

firmware returns to IDLE

timeout / ALARM

timeout

user cancels

ALARM / timeout

timeout / ALARM

new cycle

reset

reset

IDLE

MOVING_TO_CHANGE

SUCCESS

WAITING_ACK

WAITING_USER

PROBING

COMPLETING

FAILED

CANCELLED

StateButton 0 (Left)Button 1 (Center)Button 2 (Right)
IDLE / SUCCESS / FAILEDOK (encoder nav)START (if valid)BACK
MOVING_TO_CHANGE—CANCEL—
WAITING_ACK—ACK (0xA3)—
WAITING_USER$TPW (probe)FINISH (~)—
PROBING—CANCEL—
COMPLETING—CANCEL—

After a successful M61Q, a probe prompt appears asking the user whether to run the tool-setter probe ($TPW) or skip it. Navigating to the probe screen sets probeScreen::setReturnScreen(change_tool) and the result is consumed on re-entry via handleProbeScreenReturn().


File: main/display/cnc/grblhal/screens/files_screen.cpp
Detailed docs: grblhal_module_files.md

The files screen provides an SD card browser tailored to grblHAL’s flat file listing protocol. Unlike per-directory querying (used by other firmwares), grblHAL returns all files recursively in a single $F response with full absolute paths.

CommandPurpose
$FList all CNC files recursively (flat, no [DIR:] entries)
$F=<path>Run / execute a file
$FD=<path>Delete a file

No rename command exists in grblHAL. The 4-position hardware switch maps: Run / Macro / Delete / Run (position 3 repeats Run instead of Rename).

No

Yes

10s stall

$F command sent

grblHAL streams flat list

[FILE:/path/name.gcode|SIZE:n]

onFileEntryUpdate() callback

per line received

process_listing_line()

all_files_ master list populated

is_end_marker?

[FILE_LIST_END]

finalize_listing()

build_current_view()

display_file_list()

render ListMenuScreen

User navigates directory

get_parent_path() / append_to_path()

Watchdog timer (1s interval)

Timeout: show error

Key design decisions:

  • The flat all_files_ master list is built once per scan and persists across screen transitions (survives message box dialogs)
  • Directory navigation is purely local — no per-directory rescan needed
  • The [FILE_LIST_END] sentinel is synthesized by the grblHAL gcode handler on the terminating ok response
  • Memory guard: collection stops if free heap drops below 30 KB
Switch PositionActionIcon
0Run file ($F=<path>)Drive
1Toggle macro tag (pendant-side)Robot
2Delete file ($FD=<path>)Trash
3Run file again (no rename in grblHAL)Drive

File: main/display/cnc/grblhal/screens/probe_screen.cpp
Detailed docs: grblhal_module_probe.md

The probe screen executes a 4-step CNC probing sequence using standard G-code commands supported by grblHAL. It supports up to 6 axes (X/Y/Z/A/B/C) with axis naming configurable via grblHAL’s $376 parameter (UVW renaming).

screen opens

user presses START

firmware confirms IDLE\n(? query response)

[PRB:...:1] contact detected

[PRB:...:0] no contact / timeout

firmware returns to IDLE

[PRB:...:1] precise contact

[PRB:...:0] no contact / timeout

firmware returns to IDLE

user presses STOP

user presses STOP

user presses STOP

user presses STOP

ALARM / error state

ALARM

ALARM

ALARM

ALARM

new probe

retry

retry

IDLE

PRE_CHECK

SEEK

RETRACT

FAILED

FEED

APPLY_OFFSET

SUCCESS

CANCELLED

StepG-code SentDescription
PRE_CHECK? (realtime byte)Query machine state — must be IDLE to proceed
SEEKG91 G38.2 <axis><max_travel> F<feedrate>Fast first-pass probe
RETRACTG91 G1 <axis><retract> F200Back off from contact point
FEEDG91 G38.2 <axis><max_travel> F<feedrate/2>Slow precise second-pass probe
APPLY_OFFSETG10 L20 P0 <axis><offset>Set work coordinate origin

Each axis maintains its own configurable probe parameters, editable via the PanelComponent:

ParameterLabelDefault (Z)Description
OffsetO:10.0 mmTool length / surface offset applied after contact
Max TravelT:−50.0 mmMaximum probe travel (negative = downward for Z)
RetractR:3.0 mmDistance to back off before the second pass
Feed RateF:200 mm/minFirst-pass probe speed (second pass = F/2)

pos 0

pos 1

pos 2

pos 3 (≤3 axes)

pos 3 (≥4 axes)

btnAxe tap

Hardware Switch

(4 positions)

Axis X

Axis Y

Axis Z

User Lock (toggle)

Extended Axis

A / B / C

Cycles A → B → C → A

The probe screen is also callable from the Change Tool Screen as part of the M61Q post-change probe workflow. Results are communicated back via probeScreen::getResult() / setReturnScreen().


grblhal_module

cnc_shared

(main, jog, status, macros,

settings screens)

common_screens

(input_screen, message_box,

connection_status_screen)

ui_core

(UIManager, ThemeStyles,

Resources)

ESP3DValues

(observable event bus)

CNC Firmware Integration

(cnc_grblhal target:

esp3d_gcode_handler_service)

ui_components

(PanelComponent,

GenericScreen, ListMenuScreen,

VirtualButtonsComponent)

DependencyPurpose
cnc_sharedShared CNC screens (main, jog, status, macros, settings)
common_screensModal dialogs (input, message box), network scan screens
ui_coreUIManager, theme tokens, resource loading
ui_componentsPanelComponent, GenericScreen, ListMenuScreen
CNC_Firmware_Integration / cnc_grblhalgrblHAL gcode handler, PositionData, FirmwareMessage
ESP3DValuesObservable system state: firmware_status, parser_state, positions, probe_status, pin_states
translationsLocalized strings for all UI text

FeaturegrblHALgrblFluidNC
Tool change protocolT<n> M6 + 0xA3 ack + $TPW—M6T<n> (single command)
Set current toolM61Q<n>——
File listing$F flat (all files, full paths)$F per-directoryPer-directory via firmware entries
File delete$FD=<path>$FD=<path>Firmware command
File rename❌ Not supported❌ Not supported✅ Supported
SD end marker[FILE_LIST_END] (synthesized)Firmware-drivenFirmware-driven
PASSIVE / read-only mode✅ R status❌❌
Probe disconnected detection✅ |Pn:O flag❌❌
Axis UVW renaming ($376)✅❌❌