---
title: Tutorial 39 Real-Time G-code Streaming
description: Playing the printer like an instrument.
---
Tutorial 39 Real-Time G-code Streaming
1. Lesson Header
- Lesson Number: 39
- Level: Master
- Title: Real-Time G-code Streaming
- Estimated Duration: 45 Minutes
- Prerequisites: Lesson 36 (Engine), Basic Serial (Python
pyserial) - What You Will Build: A "Joystick Controller" for your printer.
2. Concept Introduction
The SD Card vs USB.
Most prints run from an SD card (buffered, reliable).
But for interactivity, we need USB Streaming.
The host (PC) sends a line (G1 X10).
The printer replies (ok).
The host sends the next line.
This allows us to change the plan mid-print.
3. Machine State Explanation
The Buffer.
The printer has a small buffer (16-32 commands).
If you send too fast, you overflow it (Printer crashes/stalls).
If you send too slow, the printer stutters (buffer underrun).
Flow Control: Wait for ok before sending the next line.
4. Command Breakdown
- Python
pyserial: Library for COM ports. - M114: Get Position (Real-time feedback).
- M112: Emergency Stop (Crucial for testing).
5. Minimal Working Example
The Sender Script.
import serial
import time
ser = serial.Serial('COM3', 115200)
time.sleep(2) # Wait for reboot
def send(cmd):
ser.write((cmd + '\n').encode())
while True:
line = ser.readline().decode().strip()
if line == 'ok': break
send("G28")
send("G1 X10 F3000")
6. Visual Representation
Interactive preview is available in the interactive reader.
7. Build Exercise
Task: Connect a Game Controller (or Keyboard) to move the printer.
Use pygame or keyboard library.
- Arrow Keys: Move X/Y.
- Space: Extrude.
- Enter: Home.
Algorithm:
Loop:
1. Read input.
2. Calculate delta_x, delta_y.
3. Send G1 X{current_x + delta_x} Y{current_y + delta_y} via relative mode (G91).
4. Wait for ok.
8. Deep Insight Section
Latency.
USB is slow.
Sending G1 X0.1 repeatedly at 60Hz floods the buffer.
Solution: Send longer moves (G1 X10) but interrupt them? No, standard G-code can't be interrupted easily.
Better Solution: Send small moves but manage the queue depth to keep it full (smooth motion) but not too full (low latency).
This is how Klipper works (mostly).
9. Common Failure Modes
- Buffer Underrun: If your Python script pauses (GC, slow calculation), the printer stops. The print gets a blob.
- Baud Rate Mismatch: 115200 vs 250000. Garbage characters.
10. Real-World Application
Sand Tables (Sisyphus).
These kinetic art tables run G-code generated on the fly by algorithms (Perlin noise, geometric patterns) that react to music or user input.
The "Slicer" runs in real-time on a Raspberry Pi.
11. Final Clean Version
The Keyboard Jogger:
import serial
import time
import keyboard # pip install keyboard
# Connect
ser = serial.Serial('COM3', 115200)
time.sleep(2)
ser.write(b"G91\n") # Relative Mode
ser.write(b"G1 F3000\n")
print("Use Arrow Keys to Move. ESC to Quit.")
while True:
cmd = None
if keyboard.is_pressed('up'): cmd = "G1 Y10"
elif keyboard.is_pressed('down'): cmd = "G1 Y-10"
elif keyboard.is_pressed('left'): cmd = "G1 X-10"
elif keyboard.is_pressed('right'): cmd = "G1 X10"
elif keyboard.is_pressed('esc'): break
if cmd:
ser.write((cmd + '\n').encode())
# Simple blocking wait (bad for smooth motion, good for safety)
while True:
if ser.in_waiting:
line = ser.readline().decode().strip()
if line == 'ok': break
time.sleep(0.1) # Debounce
ser.close()
12. Stretch Challenge
Challenge: Write a "Drawing Bot".
Use your mouse to draw on a canvas (Tkinter/PyGame).
Stream the coordinates to the printer in real-time.
Map the screen (800x600) to the bed (200x200).
Hint: You need a "Pen Up / Pen Down" logic (Z-hop).