3dSynth

Tutorials / Custom G-code

Open in the interactive tutorials reader

---
title: Tutorial 27 Math Driven G-code Generation
description: Generating G-code with Python.
---

Tutorial 27 Math Driven G-code Generation

1. Lesson Header

2. Concept Introduction

Why write G-code manually?
Manual G-code is slow.
Why use a Slicer?
Slicers are great for general models but limited for specific geometric patterns.
The Middle Ground: Scripts.
Using a high-level language (Python, JavaScript) to calculate coordinates and write the G-code file for you.
This allows loops, variables, trigonometry, and complex logic that G-code lacks.

3. Machine State Explanation

The "Generator" Pattern.
1. Define Parameters (Radius, Height, Layer Height).
2. Open a file (output.gcode).
3. Write Header (G28, G21...).
4. Loop through Layers (Z).
5. Loop through Points (X, Y).
6. Write Moves (G1 X... Y... E...).
7. Write Footer (M104 S0...).
8. Close File.

4. Command Breakdown

5. Minimal Working Example

The Hello World Script.

with open("hello.gcode", "w") as f:
    f.write("G28\n")
    f.write("G1 Z10\n")
    f.write("G1 X100 Y100\n")

6. Visual Representation

Interactive preview is available in the interactive reader.

7. Build Exercise

Task: Write a Python script to generate a Spiral Vase Cylinder.
- Radius: 20mm.
- Height: 10mm.
- Layer Height: 0.2mm.
- Segments per Circle: 64.

Algorithm:
1. Calculate total layers: Height / Layer_Height.
2. Calculate total steps: Layers * Segments.
3. For each step i:
- Angle theta = (i / Segments) * 2 * PI.
- X = Radius * cos(theta).
- Y = Radius * sin(theta).
- Z = (i / Steps) * Height.
- E += Extrusion_Per_Step.
- Write G1 X{:.3f} Y{:.3f} Z{:.3f} E{:.5f}\n.

8. Deep Insight Section

Precision.
Python floats are precise enough (15 digits).
G-code usually needs 3 decimal places (.3f).
Extrusion (E) needs 5 (.5f) to avoid accumulation errors over long prints.

Extrusion Math.
Volume of filament in = Volume of line out.
Area_filament * Length_in = Area_line * Length_out
E = (Width * Height * Length) / (PI * (1.75/2)^2)

9. Common Failure Modes

  1. Forgot Newline: f.write("G1 X10") (No \n) -> G1 X10G1 Y10 (Syntax Error).
  2. Logic Error: If your loop range is off by one, you might miss the last segment or duplicate the first.

10. Real-World Application

FullControl G-code.
A popular Python library (by Andrew Gleadall) designed exactly for this.
It handles the boilerplate (headers, extrusion math) so you just focus on the geometry.
Used for research into non-planar printing and new material structures.

11. Final Clean Version

The Script:

import math

filename = "cylinder.gcode"
radius = 20
height = 10
layer_height = 0.2
segments = 64
total_layers = int(height / layer_height)
total_steps = total_layers * segments
e_per_mm = 0.033 # Approximate for 0.4mm nozzle

with open(filename, "w") as f:
    # Header
    f.write("G21\nG90\nM83\nG28\n")
    f.write("G1 Z0.2 F3000\n")
    f.write("G1 X{} Y0\n".format(radius)) # Move to start
    
    current_e = 0
    
    for i in range(total_steps):
        angle = (i / segments) * 2 * math.pi
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)
        z = (i / total_steps) * height
        
        # Calculate distance for E (approx arc length)
        # segment_length = (2 * pi * r) / segments
        segment_length = (2 * math.pi * radius) / segments
        e_move = segment_length * e_per_mm
        
        f.write(f"G1 X{x:.3f} Y{y:.3f} Z{z:.3f} E{e_move:.5f}\n")

    # Footer
    f.write("G28 X0 Y0\n")

print(f"Generated {filename}")

12. Stretch Challenge

Challenge: Modify the script to make a Sine Wave Vase.
Vary the Radius based on Z height.
Radius = Base_Radius + Amplitude * sin(Z * Frequency).
This creates a wobbly cylinder.