THIS IS CURRENTLY ONLY DRAFT OF AN IDEA
With worry I have watched the dichotomy and complexity growth in the reprap community on two fronts.
First there is complexity in the skeiners/slicers, that have to take into account lot of machine-specific parameters, generating the code that is usable only once.
Then there is complexity in the firmware, that have to calculate in real-time the constrained dynamic movement properties, applying look-ahead, acceleration/deceleration profiles and even extrusion advance calculations.
So this all has made me think that the G-code, as it is currently, is not best suited to describe the intermediate output between the slicer and the firmware.
So here is rough outline of alternative intermediate output from slicer, something that would move more machine-specific information down in the tool chain, while keeping more semantically relevant information to aid extrusion. I believe that this would simplify both the slicer functionality and provide explicitly more information for firmware movement calculations, and possibly even reduce the need for heavy computations in the firmware. As a downside, it will create more additional processing steps.
The basic idea behind this command set was to maximize meaningful information, that is easy for a slicer to generate, and that will make it relatively simple to split up and translate into real machine movements. They do contain some optional redundant information, that might aid and simplify other components in the toolchain.
All commands are packetized, falling into following "command" categories. Most of the flags are optional and specific to the command category or command itself, their identifiers are meant to be mnemonic in nature. Parameters denoted with upper case ASCII letters are essential semantical information, lowercase letters are for redundant information that can be stripped or (re)generated as needed by intermediate steps.
At simplest level, the packet would consist of single line, it would start with command category identifier, and end with newline. Comments, in formatting similar to those in G-code could be used (semicolon to mark comment until end of line, parentheses for in-line comment).
There could be some binary format that closely shares the extensibility and style of the textual format, so that the translation would be straightforward and simple.
In case of need of packet transmission over serial line, there could be some line number/checksum algorithms available, but this is only important when post-processing steps are done in the firmware. Slicer should not generate line numbers or line checksum, but they would be added by the host program, responsible for transmission and retransmission of failed packets.
The first byte/character in the packet will describe the command category.
Number (optional for some categories) after the category character describes specific command type.
P: print commands:
These will generally cause the printer to proceed through pre-defined, configurable routines, that the slicer does not necessarily have to worry about in detail - homing, heating up/down, wiping etc. Basically, they will be just a trigger certain macros.
- P0 - declares start of print job (run predefined start command routine)
- Parameters: N### - string, describing name of the job. in case of text packet format, the name can't contain space characters
- P1 - declares end of print job (run predefined end command routine)
P0 Nvertex.stl ; start of print
L: layer definition
These are generally just descriptors that allow movement commands to refer to the appropriate Z-height and extrusion parameters with just a single number, without having to specify all of them during each move. They should be provided any time after Z movement, before sending G commands
- L0 - raft layer
- L1 - base layer
- L2 - regular layer
- L3 - partial layer/sublayer (e.g. for more fine-grained outlines)
- L## - layer absolute index
- R## - layer relative index (raft-0, raft-1, ...)
- Z### - z height
- d### - layer thickness
L1 L0 Z0.38 d0.38 ; base layer L0, absolute height Z=0.38, thickness 0.38 L2 L1 Z0.76 d0.38 ; regular layer L1, absolute height Z=0.76, thickness 0.38
G: movement commands
These are bulk of the data.
- movement type:
- G0 - travel
- G1 - stand-alone extruded filament
- G2 - support structure (raft, support)
- G3 - perimeter
- G4 - loop
- G5 - infill, inner shell layer infill
- G6 - infill, outer shell layer infill
- G7 - infill, diaphragm
- G8 - pattern infill
- X/Y: coordinates to move to
- X### Y###
- L/Z: layer reference (absolute index of the layer) or new Z coordinate
- L### or Z###
- B: overhang/bridge flags:
- B0 - shrinking perimeter - perimeter for layer smaller than previous one (underhang)
- B1 - lines up and fully supported underneath (vertical wall perimeter)
- B2 - partially unsupported underneath (overhang)
- B3 - partially supported underneath in multiple points (e.g. line infill, laying on multiple cross-points)
- B4 - fully unsupported underneath (bridge)
- A: "top" layer flags
- A1 - will not provide support to above layers
- C: perimeter curvature value
- C### (units: degrees? sine of the degree? some other formula? based on the difference to the previous extruded segment direction)
- - positive value: along positive outside curvature (e.g. outer shell on circular object)
- - negative value: along negative outside curvature (e.g. inner hole)
- M: deposition material ID (in case of multiple material extrusion)
- M### (default=same as previous movement)
- E: deposition rate volume / movement unit
- E### (non-negative value, zero means travel without intended extrusion, default=same as previous movement)
- d: distance (optional helper information, to reduce need
- d### length of movement
C: configuration commands
These are meant to set configuration parameters. Slicer does not output them, but they should probably be preloaded from configuration storage for the processor
Code processing in the toolchain
It is the responsibility of the slicer to generate this code. It should split the object into layers, generate movements, calculate volumetric extrusion, generate infill patterns, order, optimize and categorize the movement/extrusion command, to generate raft, skirt and support structures.
This can be done in relatively machine non-specific manner, only knowing the nozzle diameter and basic properties of material(s).
It is the responsibility of some kind of post-processor to generate segments of movement, look back and forward over several movements, calculate appropriate feed/extrusion rates and possibly temperatures, also perform offset calculations or switches between nozzles and materials. This is already based on parameters, specific to the machine and material(s).
This processing could be implemented as separate step, in the host or in the firmware. The output of this processing stage is not specified here, but it could be in the form of G-code or the variant/extension of the same data format. This is roughly equivalent of the output of current slicers. (maybe we can modify the specification of this data format to incorporate everything needed for that)
Second step of pre-processing involves temporal calculations, acceleration/deceleration, extrusion priming and retraction, including any advance calculation for extrusion axis (e.g. by splitting up movements).
This functionality can be implemented in firmware or in the host as pre-processing step (in case mathematical calculations involved are too slow in the firmware)
These split up movements should be combined in the firmware that supports at least look-ahead capabilities that allow movements along the same direction to continue with the current rate, without intermediate deceleration.
P0 #1*36 ; start of print, including line number and checksum L1 L0 Z0.35 d0.35 #2*2E ; define base layer G0 L0 X50.0 Y50.0 #3*51 ; move into position G3 L0 X60.0 Y50.0 M1 E0.26 C1 d10.0 #4*0E ; outline, positive curvature, extrusion 0.26 mm^3/mm G3 L0 X60.0 Y60.0 M1 E0.26 C1 d10.0 #5*1E ; outline G3 L0 X50.0 Y60.0 M1 E0.26 C1 d10.0 #6*2F ; outline G3 L0 X50.0 Y50.5 M1 E0.26 C1 d9.5 #7*97 ; outline G4 L0 X50.5 Y50.5 M1 E0.25 d0.5 #8*00 ; additional shell G4 L0 X59.5 Y50.5 M1 E0.25 d9.0 #9*00 ; additional shell G4 L0 X59.5 Y59.5 M1 E0.25 d9.0 #10*00 G4 L0 X50.5 Y59.5 M1 E0.25 d9.0 #11*00 G4 L0 X50.5 Y51.0 M1 E0.25 d8.5 #12*00 G6 ... ; fully filled infill for base layer ... L2 L1 Z0.75 d0.4 G0 L1 X50 Y50 G3 L1 B1 C1 X60 Y50 M1 E0.11 d10 ; note B1: the line is additionally explicitly specified as not being an under/overhang G3 L1 B1 C1 X60 Y60 d10 ; note the omission of repeated M and E ... G4 ... ; additional shell ... G5 ... ; fully filled infill for inner layer ... P1 ... ; end of print