Skip to content

GRBL Module

The grbl_module is the GRBL firmware-specific UI layer of the Pibot CNC pendant. It provides a complete set of LVGL screens, a connection-status overlay component, and a centralized screen router — all tuned to the classic GRBL CNC controller protocol (not FluidNC or grblHAL).

Its responsibilities are:

  • Parsing and reacting to GRBL status reports (<Idle|MPos:…>, [PRB:…], error:…, etc.) via ESP3DValues subscriptions
  • Displaying real-time machine state (positions, firmware status, pin states)
  • Letting the operator interact with the machine: tool changes, probing, file streaming, settings
  • Routing every screen-creation request to the correct create() function via a single createScreen() dispatcher

The module lives at main/display/cnc/grbl/ and is compiled only when the GRBL CNC target is selected in the build system.


Core Infrastructure

GRBL Module - main/display/cnc/grbl/

GRBL Components

Screens

Shared CNC Screens

main/display/cnc/screens/

Jog

Status

Main

Settings

Macros

Screen Router

esp3d_screen_type.cpp

createScreen()

changeTool

Screen

files

Screen

probe

Screen

Shared Screens

(main, jog, status,

settings, macros, …)

Connection Status

Component

ESP3DValues

(observables)

GCode Host

gcodeHostService

GRBL GCode

Handler

GlobalFS

(pendant SD)

UIManager

ConstraintDetail
LVGL single-threadAll UI operations run on Core 1. No LVGL calls from FreeRTOS scan tasks.
Screen transitions via timerDestruction and creation use lv_timer_create to avoid destroying objects inside event callbacks (ESP3D_TRANSITION_TIMER_BODY macro).
Value updates via subscriptionsScreens subscribe to ESP3DValues observables; callbacks are dispatched by the GRBL GCode handler on the LVGL thread.
Memory safetyAll heap allocations use std::nothrow with explicit nullptr checks. Probe parameters stored in std::map with static per-screen guard.
Cooperative cancellationThe async SD scan task checks a scan_cancel_requested flag inside its readdir loop — never force-killed.

File: main/display/cnc/grbl/screens/esp3d_screen_type.cpp

Single createScreen(ESP3DScreenType) dispatcher that maps every ESP3DScreenType enum value to the corresponding create() function. It is the only entry point for screen navigation within the GRBL module, and applies compile-time feature guards (ESP3D_WIFI_FEATURE, ESP3D_BT_SERIAL_FEATURE, etc.) so unused screen types are excluded from the binary.

→ See grbl_module_screen_router.md


File: main/display/cnc/grbl/components/connection_status.h

A lightweight LVGL overlay widget placed in the top-right corner of any screen that needs connection-state feedback. It subscribes to server_status and transport_status observables, derives a visual icon from the two-character status codes, and opens the connection_status_screen on click.

CharMeaning
?Disconnected / not connected
AAuthentication failed
TConnecting (transport or server handshake)
CConnected — full CNC control active
.Radio off

→ See grbl_module_connection_status.md


File: main/display/cnc/grbl/screens/change_tool_screen.cpp

Operator interface for CNC tool changes. Supports two modes:

  • SET mode (M61Q) — immediately sets the current tool number in firmware without movement.
  • CHANGE mode (M6T) — full automated tool change via FluidNC atc_manual macro (moves to change position → pauses for operator to install the tool → slow-feed probe).

After an M61Q, the operator is offered an optional probe step via an integrated Probe button that hands off to the probe screen and returns the result.

State machine: IDLE → MOVING_TO_CHANGE → WAITING_USER → PROBING → SUCCESS / FAILED / CANCELLED

→ See grbl_module_change_tool.md


File: main/display/cnc/grbl/screens/files_screen.cpp

File browser for the local pendant SD card (GRBL has no firmware-side SD). Key features:

  • Async directory scan (FreeRTOS task) keeps the LVGL spinner animated while the SD card is read — zero LVGL calls in the task, zero filesystem calls in the LVGL thread.
  • Four file action modes (Process/Macro/Rename/Delete) cycled via hardware switch or touch tap on the footer.
  • Job streaming via gcodeHostService.addStream() — the GCode host sends lines using ok flow-control to the connected GRBL controller.
  • Supports file extension filtering, macro tagging via MacroManager, rename, and delete.
  • Redirect mechanism: after launching a job, the screen transitions to the Status screen via a deferred timer.

→ See grbl_module_files.md


File: main/display/cnc/grbl/screens/probe_screen.cpp

CNC probe interface with a four-step state machine:

PRE_CHECK → SEEK → RETRACT → FEED → APPLY_OFFSET

Operator-configurable parameters per axis (offset, max-travel, retract distance, feedrate) are stored in a static std::map persisted across screen re-creations and edited via the shared inputScreen. Supports up to 6 axes (X Y Z A B C), grblHAL |Pn:O probe-disconnected detection, real-time pin indicators, and dynamic timeout calculation.

→ See grbl_module_probe.md


GRBL GCode HandlerESP3DValuesGrblScreen::create()createScreen()OperatorGRBL GCode HandlerESP3DValuesGrblScreen::create()createScreen()Operatorloop[Real-time updates]navigate (button / back / menu)create()Allocate LVGL objectssubscribe(firmware_status, positions, …)update(value, idx)callback(idx, value, action)Update labels / drive state machinebutton / encodersendGcode(cmd)BackprepareForDestruction()unsubscribe(all)createScreen(RETURN_SCREEN) [via lv_timer]

All GRBL screens showing MPos/WPos apply a shared throttle pattern (250 ms minimum interval) to avoid flooding the LVGL thread with 10 Hz position updates from the GRBL controller:

yes

no

yes

no

on_positions_update callback

(ESP3DValues subscription)

Elapsed < 250 ms?

Set pending flag

(wpos_pending / mpos_pending)

Store latest value

Update label(s) immediately

Reset pending flag

Record timestamp

position_flush_timer_cb

fires every 300 ms

Any pending flag set?

Read all axes from

ESP3DValues store

Update all position labels

Reset flags

No-op


The files screen uses a strict two-layer ownership model to maintain thread safety between the FreeRTOS scan task and the LVGL UI thread:

GlobalFS / SDScan Task (FreeRTOS)LVGL Task (Core 1)GlobalFS / SDScan Task (FreeRTOS)LVGL Task (Core 1)loop[Directory scan]xTaskCreate(file_scan_task)Show spinner, start scan_check_timerreaddir()Append to staging_entries_Check scan_cancel_requested flagSet scan_completed = truevTaskDelete(self)scan_check_timer_cb polls scan_completedCopy staging_entries_ → entries_Rebuild file list UIDelete scan_check_timer

Rule: The scan task never calls any lv_* function. The LVGL timer never calls any filesystem function.


ModuleRelationship
fluidnc_moduleSibling module for FluidNC firmware; identical screen structure, different GCode handler
grblhal_moduleSibling module for grblHAL firmware; adds UVW axes, $376 naming, `
UI Framework & ScreensParent module; provides GenericScreen, ListMenuScreen, UIManager, shared CNC screens (main, jog, status, settings, macros)
CNC Firmware IntegrationESP3DGCodeHandlerService (GRBL target) parses controller responses and pushes values to ESP3DValues; gcodeHostService streams GCode files
Core Platform & InfrastructureESP3DValues observable system, ESP3DSettings (NVS), logging macros
Storage & ConfigurationGlobalFileSystem used by files screen for SD listing, rename, delete

Sub-moduleDescriptionFile
Screen RouterCentralized createScreen() dispatcher for all GRBL screensgrbl_module_screen_router.md
Connection Status ComponentOverlay widget tracking connection state with click-to-opengrbl_module_connection_status.md
Change Tool ScreenM6T / M61Q tool change with state machine and optional probegrbl_module_change_tool.md
Files ScreenPendant SD file browser with async scan and GCode job streaminggrbl_module_files.md
Probe Screen4-step CNC probe sequence with per-axis parameters and pin indicatorsgrbl_module_probe.md