Macro Creation Tutorial

Part 7: The Printer Object

Many Klipper modules have what is called a get_status() wrapper these wrappers
are functions that report the state of the module. For instance, the toolhead
get_status wrapper reports things like position, max_velocity, and
max_accel. The get_status wrapper is added to the printer object
when Klipper starts up. By navigating the printer object’s hierarchy, we can obtain
all manner of useful information that can be used in macros.

The tree structure is a mish-mash of types organized in various collections. These
collections frequently have more collections nested within them. It is quite complex.

I wrote a macro to help search for values within the printer tree
(Example: Search Printer Objects) since
I can never remember the exact names of anything.

You can see by the output of it, the printer object carries booleans, floats,
strings, tuples, and even a list of lists.

printer.firmware_retraction.retract_length			: 0.75
printer.firmware_retraction.unretract_extra_length 	: 0.0
printer.firmware_retraction.unretract_speed 		: 20.0
printer.firmware_retraction.retract_speed 			: 30.0
printer.probe
printer.probe.last_query 							: False
printer.bed_mesh
printer.bed_mesh.mesh_max 							: (275.0, 275.0)
printer.bed_mesh.profile_name 						: default
printer.bed_mesh.mesh_min 							: (25.0, 25.0)
printer.bed_mesh.probed_matrix : 
	[[-0.16875, -0.16375, -0.151875, -0.165625, -0.168125], 
	[-0.1125, 0.04125, -0.063125, -0.05, -0.13875], 
	[0.020625, -0.015, -0.009375, -0.04625, -0.013125], 
	[0.023125, 0.095625, 0.0475, 0.165625, -0.041875], 
	[0.070625, 0.06375, 0.043125, 0.01625, -0.03375]]

The printer object is the cornerstone to writing useful macros because of the data
contained within it.

Say we don’t really want to have put that default pressure advance number in
there since it is already defined on the [extruder]. We can reference that
value from within our macro like so.

[gcode_macro start_print]
	gcode:
		{% if not params.PA %}
			{% set PA = printer.configfile.settings.extruder.pressure_advance %}
		{% endif %}
	
		M109 S{params.TOOL_TEMP}		# Heat the tool to temperature and wait
		
		{% if printer.homed_axes != 'XYZ' %}
			G28							#Home All Axes
		{% endif %}
	
		SET_PRESSURE_ADVANCE ADVANCE={PA}
	
		G92 E0 							# Reset Extruder
		G1 Z2.0 F3000 					# Move Z Axis to travel height
		G1 X0.1 Y20 Z0.2 F5000.0 		# Move to start position
		G1 X0.1 Y200.0 Z0.2 F1500.0 E15 # Draw the first line
		G1 X0.4 Y200.0 Z0.2 F5000.0 	# Move to side a little
		G1 X0.4 Y20 Z0.3 F1500.0 E30 	# Draw the second line
		G92 E0 							# Reset Extruder
		G1 Z2.0 F3000 					# Move Z Axis up to travel height

It should be noted, the configfile tree contains both config and
settings branches. Both trees will have all the values that were read from
the config file the last time klipper read it from the disk. The settings tree
will have all of the currently configured values as typed values where the
config tree will have them as strings only.

It should also be noted that you cannot change any of the values found in the
printer object. The only way to change anything is if there is an available gcode
to do so.

Our start print macro is going to start looking cluttered pretty quickly,
especially if we start doing comparisons and math on various values obtained
from the printer object. One thing we can do to help with this is to assign
the printer object or a specific section of it to a local variable that can
then be referenced instead. This can be done anywhere in the macro prior to
its first use, but to keep things concise, I personally prefer to put it at the top.

[gcode_macro start_print]
	gcode:
		{% set config = printer.configfile.settings %}
	
		{% if not params.PA %}
			{% set PA = config.extruder.pressure_advance %}
		{% endif %}

This is especially helpful when macros begin to get more complex like when
comparing the position of the toolhead to the axis maximum

	{% if printer.toolhead.position.z > ( printer.toolhead.axis_maximum.z - 40 ) %}

This could be made a bit tidier by assigning the position and axis limit
values to a variable and then evaluating them.

[gcode_macro end_print]
	gcode:
		{% set axismax = printer.toolhead.axis_maximum %}
		{% set pos     = printer.toolhead.position     %}
	
		#Move toolhead away from finished print
		{% if pos.z <= ( axismax.z - 40 ) %}
			G1 X10 Y10 Z{ pos.z + 40 }
		{% else %}
			G1 X10 Y10 Z{ axismax.z }
		{% endif %}
18 Likes