Printer Definition Language (PDL) Specification¶
Version: 1.0.0 Status: Draft Maintainer: OpenPrintKit Project
1. Overview¶
PDL defines a structured model for describing 3D printer capabilities, kinematics, firmware, and material behavior, independent of any slicer.
PDL aims to make printer definitions portable, verifiable, and shareable.
2. File Format¶
PDL is serialized as YAML or JSON.
File extension: .yaml, .yml, or .json.
Each PDL document must define:
| Key | Type | Required | Description |
|---|---|---|---|
pdl_version |
string | ✅ | Schema/format version |
id |
string | ✅ | Unique machine identifier (e.g. longer.lk5pro) |
name |
string | ✅ | Human-readable name |
firmware |
string | ✅ | Firmware family (marlin, klipper, etc.) |
kinematics |
string | ✅ | Motion system type |
geometry |
object | ✅ | Bed shape (polygon) and Z height |
limits |
object | ❌ | Max speeds, travel, acceleration, jerk |
extruders |
array | ❌ | One or more extruders/toolheads |
multi_material |
object | ❌ | Spool banks (e.g., AMS/MMU) and mixing |
features |
object | ❌ | Auto-bed leveling and probe details |
materials |
array | ❌ | Filament/material presets embedded in PDL |
process_defaults |
object | ❌ | Baseline print settings |
gcode |
object | ❌ | Start/end/tool-change and custom macros |
3. Example¶
pdl_version: 1.0.0
id: voron.24.350
name: Voron 2.4 (350)
firmware: klipper
kinematics: corexy
geometry:
bed_shape: [[0,0],[350,0],[350,350],[0,350]]
z_height: 350
extruders:
- id: E0
nozzle_diameter: 0.4
nozzle_type: hardened_steel
drive: direct
max_nozzle_temperature: 300
- id: E1
nozzle_diameter: 0.6
nozzle_type: brass
drive: direct
multi_material:
spool_banks:
- name: AMS-1
capacity: 4 # up to N; unlimited not enforced here
features:
auto_bed_leveling: true
probe:
type: inductive
mesh_size: [7, 7]
3.1 Extruders¶
An extruders array supports any number of extruders or toolheads. Each extruder may specify:
id: Identifier (e.g., E0, Tool-1)nozzle_diameter: e.g., 0.4nozzle_type: brass | hardened_steel | stainless | ruby | tungsten | otherdrive: direct | bowden | othermax_nozzle_temperature: temperature limit in °Cmixing_channels: number of input channels for mixing nozzles (default 1)
3.2 Multi-Material and Color Capacity¶
Use multi_material.spool_banks to model banks/carousels such as AMS or MMU. Each bank defines a capacity (integer ≥ 1). Define as many banks as needed; the schema does not impose an upper bound, enabling effectively unlimited colors when hardware permits.
Mixing nozzles can be represented by setting mixing_channels > 1 on an extruder.
3.3 Auto Bed Leveling (ABL) and Probes¶
The features object includes auto_bed_leveling and optional probe details:
probe.type: inductive | bltouch | crt | strain_gauge | nozzle_contact | manual | otherprobe.mesh_size: [rows, cols] integer tupleprobe.active_low: boolean for probe signal polarity
3.4 G-code Blocks and Macros¶
PDL captures reusable G-code sequences in the gcode object. The following keys are recognized:
start: sequence run before printingend: sequence run after printingtool_change: sequence run when changing tools/extruderslayer_change: sequence run at layer boundariespause/resume: sequences used when pausing/resuming a printfilament_change: sequence to handle manual filament changesmacros: a map of arbitrary macro names to sequences; use for additional hooks (e.g.purge_line,bed_mesh,preheat)
All fields are arrays of strings (one command per entry). macros allows named reusable sequences.
For comprehensive lifecycle coverage, PDL additionally supports both explicit fields and a generic hooks map:
-
Explicit optional fields include:
before_tool_change,after_tool_change,before_layer_change,after_layer_change,before_object,after_object,before_region,after_region,retraction,unretraction,travel_start,travel_end,bridge_start,bridge_end,top_layer_start,bottom_layer_start,support_interface_start,support_interface_end,before_heating,after_heating,before_cooling,on_abort,on_progress_percent,on_layer_interval,on_time_interval,before_snapshot,after_snapshot,power_loss_resume,auto_shutdown. -
hooksis a free-form map: keys are lower-case identifiers (letters, digits,_.-) and values are command sequences. This supports future or custom events without schema changes. Example keys:monitor.progress_25,env.lights_on,timelapse.before_snapshot.
Tip: Use conditional templating and variables provided by your slicer (e.g., {if ...}, {layer_z}, {filament_diameter[0]}) inside sequences for dynamic behavior.
3.5 Canonical Hooks Reference¶
PDL defines common, optional hook fields to cover a full-featured slicer lifecycle. If a hook is not present in gcode, it’s simply ignored.
- Global lifecycle:
start,end,on_abort,pause,resume,power_loss_resume,auto_shutdown - Tool/filament:
tool_change,before_tool_change,after_tool_change,filament_change - Layer:
layer_change,before_layer_change,after_layer_change,top_layer_start,bottom_layer_start - Object/region:
before_object,after_object,before_region,after_region - Motion/extrusion:
retraction,unretraction,travel_start,travel_end,bridge_start,bridge_end - Temperature/env:
before_heating,after_heating,before_cooling - Monitoring/timelapse:
on_progress_percent,on_layer_interval,on_time_interval,before_snapshot,after_snapshot - Support/material:
support_interface_start,support_interface_end
For additional or proprietary events, use the generic gcode.hooks map with lower-case keys (letters/digits/_.-), for example:
gcode:
hooks:
monitor.progress_25: ["M117 25%"]
env.lights_on: ["M150 R255 G255 B255"]
Minimal example snippet using placeholders and macros:
gcode:
start:
- M140 S{bed}
- M104 S{nozzle}
- G28
before_tool_change: ["G10 ; retract"]
after_tool_change: ["G11 ; unretract", "M117 Tool {tool}"]
macros:
purge_line: ["G92 E0", "G1 X0 Y0 F6000", "G1 E10 F300", "G92 E0"]
3.5 Process Defaults¶
Keys under process_defaults include:
layer_height_mm,first_layer_mmspeeds_mms: object of speeds (mm/s)perimeter,infill,travel- optional:
external_perimeter,top,bottom accelerations_mms2: object of accelerations (mm/s²)- optional:
perimeter,infill,external_perimeter,top,bottom extrusion_multiplier: scalar where 1.0 = 100%cooling:min_layer_time_s: integer secondsfan_min_percent,fan_max_percent: 0–100fan_always_on: boolean
3.6 Limits¶
Top-level machine limits that may guide generator outputs:
acceleration_max(mm/s²),jerk_max(Cura)
4. Versioning¶
-
PDL follows Semantic Versioning (SemVer):
-
Increment MAJOR when breaking schema changes occur.
-
Increment MINOR when fields are added.
-
Increment PATCH for typo or clarifications.
3.6 Materials (Embedded Filament Presets)¶
PDL may embed an array of filament/material presets under materials. Each entry typically includes:
name,filament_type, optionalfilament_diameter- Temperature/cooling:
nozzle_temperature,bed_temperature,fan_speed - Retraction:
retraction_length,retraction_speed - Color metadata:
colororcolor_hex
This is complementary to standalone Filament profiles (FDL). Use embedded presets for turnkey printer bundles, and standalone FDL for shared libraries.
3.7 Endstops (Limit Switches)¶
Use the top‑level endstops object to declare per‑axis limit switch polarity:
endstops:
x_min_active_low: true
x_max_active_low: false
y_min_active_low: true
y_max_active_low: false
z_min_active_low: true
z_max_active_low: false
If omitted, slicers or firmware defaults apply.
4. Machine-Control M-Codes (Reference)¶
For common machine-control M-codes (power, lighting, fans, probes, camera, safety, etc.) and firmware compatibility notes, see:
docs/mcode-reference.mdin the repository root.
PDL expresses these through G-code hooks and macros; use the hooks to place M-codes at appropriate lifecycle events (start/end, layer, tool-change, etc.).
3.8 Machine Control (Structured)¶
PDL can capture high-level machine control intent under machine_control. Generators translate this into G-code hooks for specific slicers or firmware:
machine_control:
psu_on_start: true # → M80 in start
psu_off_end: true # → M81 in end
light_on_start: true # → M355 S1 in start
light_off_end: true # → M355 S0 in end
rgb_start: { r: 16, g: 16, b: 16 } # → M150
chamber: { temp: 30, wait: true } # → M141 / M191
enable_mesh_start: true # → M420 S1
z_offset: -0.05 # → M851 Z-0.05
start_custom: ["M117 Startup"]
end_custom: ["M117 Finished"]
# Peripherals
camera: { use_before_snapshot: true, command: "M240" }
sd_logging: { enable_start: true, filename: "log.gco", stop_at_end: true }
fans: { part_start_percent: 50, aux_index: 1, aux_start_percent: 75, off_at_end: true }
exhaust: { enable_start: true, speed_percent: 100, off_at_end: true, pin: 10 }
aux_outputs:
- { label: Aux1, pin: 11, start_value: 255, end_value: 0 }
- { label: Aux2, pin: 12, start_value: 128 }
Tooling merges machine_control with explicit gcode hooks at generation time.