GCODE on Splicer
Splicer is controlled using a GCODE file, a standard machine control language commonly used in CNC systems. The GCODE is executed line by line, with each line representing a specific movement, control instruction, or signal trigger. The combination of spatial movement and signal commands forms the basis of Splicer’s image acquisition.
Basic Control Structure¶
Splicer interprets GCODE through a LinuxCNC-based controller, which interfaces with the machine’s hardware via a Mesa motion control board. Custom motion paths are generated using the Splicer Animator Script in Blender, which exports Blender animations as GCODE sequences.
Click here for current release of the splicer-animator
Key GCODE Commands¶
Command | Function |
---|---|
M100 |
Triggers frame capture — instructs the camera system to record a line |
M62 Pn |
Sets digital output pin n ON on the Mesa 7i96 |
M63 Pn |
Sets digital output pin n OFF on the Mesa 7i96 |
Each rising and falling edge of the output signal is interpreted as one discrete line trigger by the image capture system.
G93 Inverse Feedrate Mode¶
Splicer operates in G93
Inverse Time Feedrate Mode, which interprets feedrate (F
) as the reciprocal of the duration in minutes for executing a given GCODE move. In other words, F
defines how many such moves would occur in one minute, and the time taken for each move is calculated as T = 1 / F
(in minutes). This mode is essential for synchronizing motion with image acquisition: rather than going as fast as possible, F
controls the exact duration of the move, allowing precise control over line trigger timing during sampling. Accurate timing is critical to avoid overloading the framegrabber. Triggering lines too quickly can exceed the frequency of the acquisition system, resulting in dropped lines. On the other hand, acquiring lines too slowly leads to unnecessarily long iteration times during image capture.
Blender GCODE Export Script¶
This Python script is used to export a motion animation from Blender into machine-readable GCODE for Splicer. It generates a .ngc
file based on animated object movement, camera parameters, and output pin triggers, using G93
inverse feedrate for precise timing.
File & Capture Setup¶
import bpy
import math
from datetime import datetime
name = "ProjectName"
debug = False
path = "/Users/florianamoser/splicer_sync/"
date = datetime.now().strftime("%y%m%d")
date_time = datetime.now().strftime("%Y-%m-%d, %H:%M:%S")
filetype = ".ngc"
feedrate = "F5000"
autofocus = True
color_selected = "a"
exposure_time = 3200 # µs
name = f"{date}_{name}_{bpy.context.scene.frame_start}-{bpy.context.scene.frame_end}"
Blender Object References¶
obj = bpy.data.objects["Sample"]
obj_cam = bpy.data.objects["Camera"]
cam = bpy.data.cameras["Camera"]
GCODE File Header¶
outF = open(path + name + filetype, "w")
outF.write("%\n")
outF.write(f"({date_time}, Florian Amoser)\n")
outF.write("(This is machine specific gcode for SPLICER)\n")
outF.write(f"({name + filetype})\n")
outF.write(f"(linenumbers: {bpy.context.scene.frame_end - bpy.context.scene.frame_start})\n")
outF.write(f"(color: {color_selected})\n")
outF.write(f"(exposure time: {exposure_time}μs)\n")
outF.write("G90 G17\nG21\nG01 " + feedrate + "\n")
Move to Starting Position + Trigger¶
bpy.context.scene.frame_set(bpy.context.scene.frame_start)
outF.write("G0 X... Y... Z... A... B... C... U...\n") # Initial move command
outF.write("M100\n") # Start external trigger
Frame-by-Frame Motion Export¶
Each frame is read from the Blender animation and translated into spatial coordinates, then written as a G-code line with:
G93 G1
motion blockF...
inverse feedrateM62 P0
orM63 P0
line trigger pulseX Y Z A B C U V
axis positions (only if changed from previous)
Autofocus Calculation (Polynomial Fit)¶
More on this in the autofocus calibration chapter.
pos["v"] = round(
(361.142 - 2.44684 * fy + 0.00897864 * fy**2
- 0.0000177572 * fy**3 + 0.0000000195082 * fy**4
- 1.11954E-11 * fy**5 + 2.61487E-15 * fy**6), 3)
Where fy = pos["y"] + pos["focus_offset"]
.
Inverse Feedrate Timing¶
GCODE uses G93
mode, Feedrate is set with:
outF.write(" F20000")
This defines the move time as 1 / (20000 / 60)
minutes.
End-of-File¶
Return to start position and write G-code footer:
outF.write("G0 X... Y... Z... A... B... C... U...\n")
outF.write("%")
outF.close()
print(date_time + " exported: " + name + filetype)
This script forms the core of Splicer's time-based motion programming and is integral to coordinating physical sampling with the framegrabber's triggering logic. To learn how to use it refer to the chapter Splicer Animator.