Our G-Code API provides a way to use G-Codes to control Zaber devices. The library interprets the codes and outputs Zaber ASCII protocol stream commands. You can review the usage of Streams in this article and the stream commands in the protocol manual.
This article assumes a basic understanding of G-Code. For example, Linux CNC offers a great reference.
Starting with basic G-Code translation is easy.
# from zaber_motion.gcode import Translator
stream = device.streams.get_stream(1)
stream.setup_live(1, 2)
translator = Translator.setup(stream)
translator.translate("G28")
translator.translate("G0 X100")
translator.translate("G0 Y100")
translator.translate("G0 X0 Y0")
translator.flush()
stream.disable()
First, you need to set up a live stream over the designated axes.
Then, set up an instance of the
Translator
class over the stream.
Afterward, you can start translating G-Code by calling the
translate
method.
The device may not start moving immediately after calling
because the instructions are buffered in the library for optimization.
Additionally, the movements are also queued in the device to allow for smooth motion.
To ensure that the library sends all the movements, call the
flush
method.
The method also waits for the device to finish all the queued movements.
At the end, we should call the
disabled
method to release the axes from the stream.
The
translate
method also returns a the
TranslateResult
data class instance.
The instance contains generated commands as well as warnings produced during translation.
The warnings can be useful in determining ignored or unknown instructions.
result = translator.translate("G28 G999")
print(result)
# {'_commands': ['on a b line abs 0 0'],
# '_warnings': [{'_message': 'Unknown command G999.', '_from_block': 4, '_to_block': 8}]}
Additionally the translation can throw the
GCodeSyntaxException
and the
GCodeExecutionExceptionexceptions containing details of what went wrong.
The translator's
setup
method takes additional argument for configuring the translator.
translator = Translator.setup(stream, TranslatorConfig(
axis_mappings=[
AxisMapping('X', axis_index=1),
AxisMapping('Y', axis_index=0)
],
axis_transformations=[
AxisTransformation("X", scaling=-1),
AxisTransformation("Y", translation=Measurement(20, Units.LENGTH_MILLIMETRES)),
],
))
You can use the configuration to remap translator axes or transform the coordinates of an axis.
For example, you can invert the axis by specifying scaling=-1
or offset it by 20 mm by specifying translation.
The translator support 9 coordinate system: G54-G59 and G59.1-G59.3.
You can set coordinate system offset by programming G10 L2 P? where P? is the coordinate system number (G54 is P1).
You can also retrieve currently used coordinate system or an offset of axis in a given coordinate system.
See the example below.
translator.translate("G10 L2 P3 X200 Y50") # set up offset for G56
translator.translate("G56") # select G56
print(translator.coordinate_system)
# prints G56
offset = translator.get_axis_coordinate_system_offset("G56", "X", Units.LENGTH_MILLIMETRES)
print(offset)
# prints 200
It's often useful to interact with other hardware on top of Zaber devices.
You can, for example, use M-code M3 to turn on a spindle of a milling machine with digital input on Zaber controller.
The example below demonstrates exactly that.
with open("C:\\prototype.tap") as file:
while True:
line = file.readline()
if not line:
break # EOF
else if line == "M3":
translator.flush() # finish all queued movements
stream.set_digital_output(1, DigitalOutputAction.ON) # turn on digital output
time.sleep(30) # wait 30 seconds for the spindle to reach full speed
else:
translator.translate(line)
It is crucial to always call the
flush
method before interacting with other hardware.
By calling the method, you ensure that the device has reached the final position in the submitted G-Code.
If you also perform some movement outside of G-Code, make sure to call the
reset_position
method afterwards.
The method queries the device and updates translator's internal position to match the device.
Alternatively, you can use the
set_position
method to update the position manually.
Using patterns like the one above, you can interact with any external hardware like PLC, laser, pumps, etc.
We provide a special M-Code M700 that allows to pass stream commands directly to the underlying stream.
The commands are provided in G-Code comments with parentheses.
result = translator.translate("M700 (wait io ai 1 >= 0.5) (wait 200)")
print(result)
# {'_commands': ['wait io ai 1 >= 0.5', 'wait 200'],
# '_warnings': []}
The example above passes two commands to the stream.
The first one waits for analog input 1 to get above 0.5 V.
The second one then waits additional 200 ms.
The translator supports continuous path mode (G64) where it rounds corners of line segments to maintain speed.
The current implementation has certain limitations.
Firstly, the corners are only rounded up to a specified path deviation from a corner
(in contrast to milling machines' ability to maintain constant milling speed).
You can specify the deviation with P parameter; otherwise, the default value of 0.1 mm applies.
Secondly, the translator only looks ahead at two consequent linear movements and always reaches each segment at worst case as a tangent.
G64 is a default path control mode.
In addition to G64 the translator also supports exact path mode G61 and exact stop mode G61.1.
Use these modes to enforce the exact travel of the specified path.
You may also use G9 exact stop instruction to enforce stopping after a single block.
The translator supports the feed rate (F) parameter for movements.
The feed rate is specified in millimetres per minute. For example:
G1 X100 F1000 (move by 100 mm at 1000 mm/min)
Note that the first non-rapid movement must have the feed rate specified. Otherwise, the translator will throw an exception.
Additionally, you can use the
set_feed_rate_override
method to change the feed rate during translation.
For example, the following code slows down all the non-rapid movements by half of the original feed rate.
translator.set_feed_rate_override(0.5)
The inverse time feed rate mode (G93) and units per revolution feed rate mode (G95) are not supported.
In addition to streaming G-Code directly to the device, we also provide a way to translate instructions without sending the commands. You can, for example, use this for simulation purposes or processing of the generated commands.
# from zaber_motion.gcode import OfflineTranslator
translator = OfflineTranslator.setup(DeviceDefinition(device_id=30331, axes=[
AxisDefinition(peripheral_id=70245, microstep_resolution=64),
AxisDefinition(peripheral_id=70245, microstep_resolution=64),
AxisDefinition(peripheral_id=70245, microstep_resolution=64),
], max_speed=Measurement(100, Units.VELOCITY_MILLIMETRES_PER_SECOND)))
result = translator.translate("G28")
print(result)
# {'_commands': ['on a b c line abs 0 0 0'], '_warnings': [] }
In order to create an offline translator, you have to specify information about the device (
TranslatorConfig
).
You can find this information by accessing device settings in Zaber Launcher.
The interface of the
OfflineTranslator
class is nearly identical the one of the
Translator
class
with notable exception of
translate
and
flush
methods being synchronous.
The translator supports a wide range of semi-standard G-Codes and M-Codes.
G0 - traverse lineG1 - lineG2, G3 - arc, without support for parameters R and PG4 - dwell (P in seconds)G10 - set coordinate system (L2 only)G17, G18, G19 - plane selectionG21 - millimeter system selectionG28, G28.1 - return to home, set home to the current positionG30, G30.1 - return to secondary home, set secondary home to the current positionG53 - machine coordinate systemG54-G59, G59.1-G59.3 - coordinate system selectionG61, G61.1, G64 - path control modeG90, G91 - absolute/relative mode (G91 is default)G90.1, G91.1 - absolute/relative arc distance mode (G91.1 is default)G92, G92.1 - temporary work offset (not recommended)M2, M30 - program stop and endM64, M65 - set digital outputM66 - wait on input (E not supported; L0,L1,L2 not supported; Q not supported; use M700 when possible)M68 - set analog outputIf you require support of some additional codes for your application, please let us know.
There are some codes that we explicitly don't support at this moment.
G20 - inch system selectionG40, G41, G42 - tool radius compensationG43, G44, G49 - tool length compensationG93 - inverse time feed rate modeG95 - units per revolution feed rate modeHere you find all non-standard codes specific to our implementation.
M700 - stream command passthrough