3dSynth

Tutorials / Custom G-code

Open in the interactive tutorials reader

---
title: Tutorial 28 Designing a Mini G-code DSL
description: Creating your own language for 3D printing.
---

Tutorial 28 Designing a Mini G-code DSL

1. Lesson Header

2. Concept Introduction

What is a DSL?
A Domain Specific Language.
G-code is a low-level assembly language (G1 X10 Y10).
We want a high-level language:
square(10)
circle(20)
move_to(50, 50)

This abstraction hides the complexity of G1, E calculations, and coordinate tracking.

3. Machine State Explanation

The "Context" Object.
To build a DSL, we need an object (in Python/JS) that tracks the machine state virtually.
- Current X, Y, Z.
- Current E (Total extruded).
- Current Speed.
- Mode (Relative/Absolute).

When you call move(10), the context updates its internal X position and writes the corresponding G1 command.

4. Command Breakdown

5. Minimal Working Example

The Turtle.
Imagine a Logo Turtle that extrudes plastic.
t = Turtle()
t.forward(10) -> Writes G1 X10 E...
t.right(90) -> Updates internal angle.

6. Visual Representation

Interactive preview is available in the interactive reader.

7. Build Exercise

Task: Build a Python Class GcodeTurtle.
Methods:
- __init__(filename): Open file.
- set_speed(f): Write G1 F....
- move(dist): Move forward dist mm. Calculate new X/Y based on angle.
- turn(angle): Update internal angle.
- extrude(amount): Move E axis.
- finish(): Write footer and close.

Usage:

bot = GcodeTurtle("turtle.gcode")
bot.set_speed(3000)
for i in range(4):
    bot.move(50)
    bot.turn(90)
bot.finish()

8. Deep Insight Section

Abstraction Cost.
Every layer of abstraction adds overhead but increases safety.
Our GcodeTurtle can automatically check boundaries:
"If next_x > 200, raise Error: 'Out of Bounds'".
Raw G-code would just crash the printer.

9. Common Failure Modes

  1. State Drift: If your Python math (float) drifts from the printer's internal step count (int), long prints might end up slightly off. (Usually negligible).
  2. Z-Tracking: Turtles are usually 2D. Adding up() and down() for Z-hops requires tracking Z state carefully.

10. Real-World Application

Parametric CAD to G-code.
Some workflows export solid or mesh geometry and slice it directly.
SVG to G-code.
Laser cutter software (LightBurn) reads vector shapes (DSL) and converts them to G-code paths.

11. Final Clean Version

The Mini-Engine:

import math

class GcodeTurtle:
    def __init__(self, filename):
        self.f = open(filename, "w")
        self.x = 0
        self.y = 0
        self.z = 0
        self.e = 0
        self.angle = 0 # Degrees
        self.e_per_mm = 0.05
        
        # Header
        self.f.write("G21\nG90\nM83\nG28\nG1 Z0.2 F3000\n")

    def set_speed(self, speed):
        self.f.write(f"G1 F{speed}\n")

    def move(self, distance, extrude=True):
        rad = math.radians(self.angle)
        dx = distance * math.cos(rad)
        dy = distance * math.sin(rad)
        
        self.x += dx
        self.y += dy
        
        cmd = f"G1 X{self.x:.3f} Y{self.y:.3f}"
        if extrude:
            e_amount = distance * self.e_per_mm
            cmd += f" E{e_amount:.5f}"
            self.e += e_amount
            
        self.f.write(cmd + "\n")

    def turn(self, angle):
        self.angle += angle

    def finish(self):
        self.f.write("G28 X0 Y0\n")
        self.f.close()
        print("Done.")

# Usage
t = GcodeTurtle("square.gcode")
t.set_speed(2000)
for _ in range(36): # 36-sided polygon (Circle-ish)
    t.move(10)
    t.turn(10)
t.finish()

12. Stretch Challenge

Challenge: Add arc(radius, angle) to the Turtle.
This is hard!
You have to calculate the center of the circle based on current heading and radius, then issue a G2 or G3 command.
G2 X[Target] Y[Target] I[Offset] J[Offset].
Hint: The Offset (I, J) is the vector from Start Point to Center.