klipper_config/macros/timelapse.cfg

417 lines
No EOL
21 KiB
INI

# Timelapse klipper macro definition
#
# Copyright (C) 2021 Christoph Frei <fryakatkop@gmail.com>
# Copyright (C) 2021 Alex Zellner <alexander.zellner@googlemail.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license
#
# Macro version 1.7
#
##### DO NOT CHANGE ANY MACRO!!! #####
##########################################################################
# #
# GET_TIMELAPSE_SETUP: Print the Timelapse setup to console #
# #
##########################################################################
[gcode_macro GET_TIMELAPSE_SETUP]
description: Print the Timelapse setup
gcode:
{% set tl = printer['gcode_macro TIMELAPSE_TAKE_FRAME'] %}
{% set output_txt = ["Timelapse Setup:"] %}
{% set _dummy = output_txt.append("enable: %s" % tl.enable) %}
{% set _dummy = output_txt.append("park: %s" % tl.park.enable) %}
{% if tl.park.enable|lower == 'true' %}
{% set _dummy = output_txt.append("park position: %s time: %s s" % (tl.park.pos, tl.park.time)) %}
{% if tl.park.pos|lower == 'custom' %}
{% set _dummy = output_txt.append("custom cord x:%s y:%s dz:%s" % (tl.custom.x, tl.custom.y, tl.custom.dz)) %}
{% endif %}
{% set _dummy = output_txt.append("travel speed: %s mm/s" % tl.speed.travel) %}
{% endif %}
{% set _dummy = output_txt.append("fw_retract: %s" % tl.extruder.fw_retract) %}
{% if tl.extruder.fw_retract|lower == 'false' %}
{% set _dummy = output_txt.append("retract: %s mm speed: %s mm/s" % (tl.extruder.retract, tl.speed.retract)) %}
{% set _dummy = output_txt.append("extrude: %s mm speed: %s mm/s" % (tl.extruder.extrude, tl.speed.extrude)) %}
{% endif %}
{% set _dummy = output_txt.append("verbose: %s" % tl.verbose) %}
{action_respond_info(output_txt|join("\n"))}
################################################################################################
# #
# Use _SET_TIMELAPSE_SETUP [ENABLE=value] [VERBOSE=value] [PARK_ENABLE=value] [PARK_POS=value] #
# [PARK_TIME=value] [CUSTOM_POS_X=value] [CUSTOM_POS_Y=value] #
# [CUSTOM_POS_DZ=value][TRAVEL_SPEED=value] [RETRACT_SPEED=value] #
# [EXTRUDE_SPEED=value] [EXTRUDE_DISTANCE=value] #
# [RETRACT_DISTANCE=value] [FW_RETRACT=value] #
# #
################################################################################################
[gcode_macro _SET_TIMELAPSE_SETUP]
description: Set user parameters for timelapse
gcode:
##### get dictonaries #####
{% set enable = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].enable %}
{% set verbose = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].verbose %}
{% set park = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].park %}
{% set custom = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].custom %}
{% set speed = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].speed %}
{% set extruder = printer['gcode_macro TIMELAPSE_TAKE_FRAME'].extruder %}
##### get min and max bed size #####
{% set min = printer.toolhead.axis_minimum %}
{% set max = printer.toolhead.axis_maximum %}
##### set new values #####
{% if params.ENABLE is defined %}
{% if params.ENABLE|lower == 'true' or params.ENABLE|lower == 'false' %}
{% set enable = params.ENABLE|capitalize %}
{% else %}
{action_raise_error("ENABLE=%s not supported. Allowed values are [True, False]" % params.ENABLE)}
{% endif %}
{% endif %}
{% if params.VERBOSE is defined %}
{% if params.VERBOSE|lower == 'true' or params.VERBOSE|lower == 'false' %}
{% set verbose = params.VERBOSE|capitalize %}
{% else %}
{action_raise_error("VERBOSE=%s not supported. Allowed values are [True, False]" % params.VERBOSE)}
{% endif %}
{% endif %}
{% if params.PARK_ENABLE is defined %}
{% if params.PARK_ENABLE|lower == 'true' or params.PARK_ENABLE|lower == 'false' %}
{% set _dummy = park.update({'enable':params.PARK_ENABLE|capitalize}) %}
{% else %}
{action_raise_error("PARK_ENABLE=%s not supported. Allowed values are [True, False]" % params.PARK_ENABLE)}
{% endif %}
{% endif %}
{% if params.PARK_POS is defined %}
{% if params.PARK_POS|lower == 'center' or params.PARK_POS|lower == 'front_left' or params.PARK_POS|lower == 'front_right'
or params.PARK_POS|lower == 'back_left' or params.PARK_POS|lower == 'back_right' or params.PARK_POS|lower == 'custom' %}
{% set _dummy = park.update({'pos':params.PARK_POS|lower}) %}
{% else %}
{action_raise_error("PARK_POS=%s not supported. Allowed values are [CENTER, FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, CUSTOM]"
% params.PARK_POS)}
{% endif %}
{% endif %}
{% if params.PARK_TIME is defined %}
{% if params.PARK_TIME|float >= 0.0 %}
{% set _dummy = park.update({'time':params.PARK_TIME|float|round(3)}) %}
{% else %}
{action_raise_error("PARK_TIME=%s must be a positive number" % params.PARK_TIME)}
{% endif %}
{% endif %}
{% if params.CUSTOM_POS_X is defined %}
{% if params.CUSTOM_POS_X|float >= min.x and params.CUSTOM_POS_X|float <= max.x %}
{% set _dummy = custom.update({'x':params.CUSTOM_POS_X|float|round(3)}) %}
{% else %}
{action_raise_error("CUSTOM_POS_X=%s must be within [%s - %s]" % (params.CUSTOM_POS_X, min.x, max.x))}
{% endif %}
{% endif %}
{% if params.CUSTOM_POS_Y is defined %}
{% if params.CUSTOM_POS_Y|float >= min.y and params.CUSTOM_POS_Y|float <= max.y %}
{% set _dummy = custom.update({'y':params.CUSTOM_POS_Y|float|round(3)}) %}
{% else %}
{action_raise_error("CUSTOM_POS_Y=%s must be within [%s - %s]" % (params.CUSTOM_POS_Y, min.y, max.y))}
{% endif %}
{% endif %}
{% if params.CUSTOM_POS_DZ is defined %}
{% if params.CUSTOM_POS_DZ|float >= min.z and params.CUSTOM_POS_DZ|float <= max.z %}
{% set _dummy = custom.update({'dz':params.CUSTOM_POS_DZ|float|round(3)}) %}
{% else %}
{action_raise_error("CUSTOM_POS_DZ=%s must be within [%s - %s]" % (params.CUSTOM_POS_DZ, min.z, max.z))}
{% endif %}
{% endif %}
{% if params.TRAVEL_SPEED is defined %}
{% if params.TRAVEL_SPEED|float > 0.0 %}
{% set _dummy = speed.update({'travel':params.TRAVEL_SPEED|float|round(3)}) %}
{% else %}
{action_raise_error("TRAVEL_SPEED=%s must be larger than 0" % params.TRAVEL_SPEED)}
{% endif %}
{% endif %}
{% if params.RETRACT_SPEED is defined %}
{% if params.RETRACT_SPEED|float > 0.0 %}
{% set _dummy = speed.update({'retract':params.RETRACT_SPEED|float|round(3)}) %}
{% else %}
{action_raise_error("RETRACT_SPEED=%s must be larger than 0" % params.RETRACT_SPEED)}
{% endif %}
{% endif %}
{% if params.EXTRUDE_SPEED is defined %}
{% if params.EXTRUDE_SPEED|float > 0.0 %}
{% set _dummy = speed.update({'extrude':params.EXTRUDE_SPEED|float|round(3)}) %}
{% else %}
{action_raise_error("EXTRUDE_SPEED=%s must be larger than 0" % params.EXTRUDE_SPEED)}
{% endif %}
{% endif %}
{% if params.EXTRUDE_DISTANCE is defined %}
{% if params.EXTRUDE_DISTANCE|float >= 0.0 %}
{% set _dummy = extruder.update({'extrude':params.EXTRUDE_DISTANCE|float|round(3)}) %}
{% else %}
{action_raise_error("EXTRUDE_DISTANCE=%s must be specified as positiv number" % params.EXTRUDE_DISTANCE)}
{% endif %}
{% endif %}
{% if params.RETRACT_DISTANCE is defined %}
{% if params.RETRACT_DISTANCE|float >= 0.0 %}
{% set _dummy = extruder.update({'retract':params.RETRACT_DISTANCE|float|round(3)}) %}
{% else %}
{action_raise_error("RETRACT_DISTANCE=%s must be specified as positiv number" % params.RETRACT_DISTANCE)}
{% endif %}
{% endif %}
{% if params.FW_RETRACT is defined %}
{% if params.FW_RETRACT|lower == 'true' or params.FW_RETRACT|lower == 'false' %}
{% if 'firmware_retraction' in printer.configfile.settings %}
{% set _dummy = extruder.update({'fw_retract':params.FW_RETRACT|capitalize}) %}
{% else %}
{% set _dummy = extruder.update({'fw_retract':False}) %}
{% if params.FW_RETRACT|lower == 'true' %}
{action_raise_error("[firmware_retraction] not defined in printer.cfg. Can not enanble fw_retract")}
{% endif %}
{% endif %}
{% else %}
{action_raise_error("FW_RETRACT=%s not supported. Allowed values are [True, False]" % params.FW_RETRACT)}
{% endif %}
{% endif %}
##### write values to variables #####
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=enable VALUE='"{enable}"'
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=verbose VALUE='"{verbose}"'
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=park VALUE="{park}"
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=custom VALUE="{custom}"
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=speed VALUE="{speed}"
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=extruder VALUE="{extruder}"
##########################################################################
# #
# TIMELAPSE_TAKE_FRAME: take the next picture #
# #
##########################################################################
######################### definition #########################
## enable: enable or disable the next frame. Valid inputs: [True, False]
## takingframe: internal use. Valid inputs: [True, False]
##
## park.enable: enable or disable to park the head while taking a picture. Valid inputs: [True, False]
## park.pos : used position for parking. Valid inputs: [center, front_left, front_right, back_left, back_right, custom]
## park.time : used for the debug macro. Time in s
##
## custom.x, custom.y: coordinates of the custom parkposition. Unit [mm]
## custom.dz : custom z hop for the picture. Unit [mm]
##
## extruder.fw_retract: enable disable fw retraction [True,False]
## extruder.extrude. : filament extruded at the end of park. Unit [mm]
## extruder.retract. : filament retract at the start of park. Unit [mm]
##
## speed.travel : used speed for travel from and to the park positon. Unit: [mm/min]
## speed.retract: used speed for retract [mm/min]
## speed.extrude: used speed for extrude [mm/min]
##
## verbose: Enable mesage output of TIMELAPSE_TAKE_FRAME
##
## restore.absolute.coordinates: internal use
## restore.absolute.extrude : internal use
## restore.speed : internal use
## restore.e : internal use
##
## is_paused: internal use
###############################################################
[gcode_macro TIMELAPSE_TAKE_FRAME]
description: Take Timelapse shoot
variable_enable: False
variable_takingframe: False
variable_park: {'enable': False,
'pos' : 'center',
'time' : 0.1}
variable_custom: {'x': 0, 'y': 0, 'dz': 0}
variable_extruder: {'fw_retract': False,
'retract': 1.0,
'extrude': 1.0}
variable_speed: {'travel': 100,
'retract': 15,
'extrude': 15}
variable_verbose: True
variable_restore: {'absolute': {'coordinates': True, 'extrude': True}, 'speed': 1500, 'e':0}
variable_is_paused: False
gcode:
##### get input parameters #####
{% set hyperlapse = params.HYPERLAPSE|default('false')|lower %}
##### define park position #####
{% set min = printer.toolhead.axis_minimum %}
{% set max = printer.toolhead.axis_maximum %}
{% set act = printer.toolhead.position %}
{% set pos_dic = {'center' : {'x': (max.x-(max.x-min.x)/2), 'y': (max.y-(max.y-min.y)/2), 'dz': 1 },
'front_left' : {'x': min.x , 'y': min.y , 'dz': 0 },
'front_right': {'x': max.x , 'y': min.y , 'dz': 0 },
'back_left' : {'x': min.x , 'y': max.y , 'dz': 0 },
'back_right' : {'x': max.x , 'y': max.y , 'dz': 0 },
'custom' : {'x': custom.x , 'y': custom.y , 'dz': custom.dz}} %}
##### check z max #####
{% if (act.z|float + pos_dic[park.pos].dz|float) < max.z|float %}
{% set pos = {'x': pos_dic[park.pos].x, 'y': pos_dic[park.pos].y, 'z': (act.z|float + pos_dic[park.pos].dz|float)} %}
{% else %}
{% set pos = {'x': pos_dic[park.pos].x, 'y': pos_dic[park.pos].y, 'z': max.z} %}
{% endif %}
##### end of definition #####
{% if enable|lower == 'true' %}
{% if (hyperlapse == 'true' and printer['gcode_macro HYPERLAPSE'].run|lower == 'true') or
(hyperlapse == 'false' and printer['gcode_macro HYPERLAPSE'].run|lower == 'false') %}
{% if park.enable|lower == 'true' %}
{% set restore = {'absolute': {'coordinates': printer.gcode_move.absolute_coordinates,
'extrude' : printer.gcode_move.absolute_extrude},
'speed' : printer.gcode_move.speed,
'e' : printer.gcode_move.gcode_position.e} %}
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=restore VALUE="{restore}"
{% if printer.extruder.can_extrude|lower == 'false' %}
{action_respond_info("Timelapse: Warning, minimum extruder temperature not reached!")}
{% else %}
{% if extruder.fw_retract|lower == 'true' %}
G10
{% else %}
M83 ; insure relative extrusion
G0 E-{extruder.retract} F{speed.retract|int * 60}
{% endif %}
{% endif %}
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=is_paused VALUE=True
{printer.configfile.settings['gcode_macro pause'].rename_existing} ; execute the klipper PAUSE command
G90 ; insure absolute move
{% if "xyz" not in printer.toolhead.homed_axes %}
{action_respond_info("Timelapse: Warning, axis not homed yet!")}
{% else %}
G0 X{pos.x} Y{pos.y} Z{pos.z} F{speed.travel|int * 60}
{% endif %}
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=takingframe VALUE=True
UPDATE_DELAYED_GCODE ID=_WAIT_TIMELAPSE_TAKE_FRAME DURATION=0.5
M400
{% endif %}
_TIMELAPSE_NEW_FRAME HYPERLAPSE={hyperlapse}
{% endif %}
{% else %}
{% if verbose|lower == 'true' %}
{action_respond_info("Timelapse: disabled, take frame ignored")}
{% endif %}
{% endif %}
[gcode_macro _TIMELAPSE_NEW_FRAME]
description: action call for timelapse shoot. must be a seperate macro
gcode:
{action_call_remote_method("timelapse_newframe",
macropark=printer['gcode_macro TIMELAPSE_TAKE_FRAME'].park,
hyperlapse=params.HYPERLAPSE)}
[delayed_gcode _WAIT_TIMELAPSE_TAKE_FRAME]
gcode:
{% set tl = printer['gcode_macro TIMELAPSE_TAKE_FRAME'] %}
{% if tl.takingframe %}
UPDATE_DELAYED_GCODE ID=_WAIT_TIMELAPSE_TAKE_FRAME DURATION=0.5
{% else %}
{printer.configfile.settings['gcode_macro resume'].rename_existing} VELOCITY={tl.speed.travel} ; execute the klipper RESUME command
SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=is_paused VALUE=False
{% if printer.extruder.can_extrude|lower == 'false' %}
{action_respond_info("Timelapse: Warning minimum extruder temperature not reached!")}
{% else %}
{% if tl.extruder.fw_retract|lower == 'true' %}
G11
{% else %}
G0 E{tl.extruder.extrude} F{tl.speed.extrude|int * 60}
G0 F{tl.restore.speed}
{% if tl.restore.absolute.extrude|lower == 'true' %}
M82
G92 E{tl.restore.e}
{% endif %}
{% endif %}
{% endif %}
{% if tl.restore.absolute.coordinates|lower == 'false' %} G91 {% endif %}
{% endif %}
####################################################################################################
# #
# HYPERLAPSE: Starts or stops a Hyperlapse video #
# Usage: HYPERLAPSE ACTION=START [CYCLE=time] starts a hyperlapse with cycle time (default 30 sec) #
# HYPERLAPSE ACTION=STOP stops the hyperlapse recording #
# #
####################################################################################################
######################### definition #########################
## cycle: cycle time in seconds
## run: internal use [True/False]
###############################################################
[gcode_macro HYPERLAPSE]
description: Start/Stop a hyperlapse recording
variable_cycle: 0
variable_run: False
gcode:
{% set cycle = params.CYCLE|default(30)|int %}
{% if params.ACTION is defined and params.ACTION|lower == 'start' %}
{action_respond_info("Hyperlapse: frames started (Cycle %d sec)" % cycle)}
SET_GCODE_VARIABLE MACRO=HYPERLAPSE VARIABLE=run VALUE=True
SET_GCODE_VARIABLE MACRO=HYPERLAPSE VARIABLE=cycle VALUE={cycle}
UPDATE_DELAYED_GCODE ID=_HYPERLAPSE_LOOP DURATION={cycle}
TIMELAPSE_TAKE_FRAME HYPERLAPSE="True"
{% elif params.ACTION is defined and params.ACTION|lower == 'stop' %}
SET_GCODE_VARIABLE MACRO=HYPERLAPSE VARIABLE=run VALUE=False
{action_respond_info("Hyperlapse: frames stopped")}
UPDATE_DELAYED_GCODE ID=_HYPERLAPSE_LOOP DURATION=0
{% else %}
{action_respond_info("Hyperlapse: No valid input parameter
Use:
- HYPERLAPSE ACTION=START [CYCLE=time]
- HYPERLAPSE ACTION=STOP")}
{% endif %}
[delayed_gcode _HYPERLAPSE_LOOP]
gcode:
UPDATE_DELAYED_GCODE ID=_HYPERLAPSE_LOOP DURATION={printer["gcode_macro HYPERLAPSE"].cycle}
TIMELAPSE_TAKE_FRAME HYPERLAPSE="True"
##########################################################################
# #
# TIMELAPSE_RENDER: Render the video at print end #
# #
##########################################################################
######################### definition #########################
## render: internal use. Valid inputs: [True, False]
## run_identifier: internal use. Valid input [0 .. 3]
###############################################################
[gcode_macro TIMELAPSE_RENDER]
description: Render Timelapse video and wait for the result
variable_render: False
variable_run_identifier: 0
gcode:
{action_respond_info("Timelapse: Rendering started")}
{action_call_remote_method("timelapse_render", byrendermacro="True")}
SET_GCODE_VARIABLE MACRO=TIMELAPSE_RENDER VARIABLE=render VALUE=True
{printer.configfile.settings['gcode_macro pause'].rename_existing} ; execute the klipper PAUSE command
UPDATE_DELAYED_GCODE ID=_WAIT_TIMELAPSE_RENDER DURATION=0.5
[delayed_gcode _WAIT_TIMELAPSE_RENDER]
gcode:
{% set ri = printer['gcode_macro TIMELAPSE_RENDER'].run_identifier|int % 4 %}
SET_GCODE_VARIABLE MACRO=TIMELAPSE_RENDER VARIABLE=run_identifier VALUE={ri + 1}
{% if printer['gcode_macro TIMELAPSE_RENDER'].render %}
M117 Rendering {['-','\\','|','/'][ri]}
UPDATE_DELAYED_GCODE ID=_WAIT_TIMELAPSE_RENDER DURATION=0.5
{% else %}
{action_respond_info("Timelapse: Rendering finished")}
M117
{printer.configfile.settings['gcode_macro resume'].rename_existing} ; execute the klipper RESUME command
{% endif %}
##########################################################################
# #
# TEST_STREAM_DELAY: Helper macro to find stream and park delay #
# #
##########################################################################
[gcode_macro TEST_STREAM_DELAY]
description: Helper macro to find stream and park delay
gcode:
{% set min = printer.toolhead.axis_minimum %}
{% set max = printer.toolhead.axis_maximum %}
{% set act = printer.toolhead.position %}
{% set tl = printer['gcode_macro TIMELAPSE_TAKE_FRAME'] %}
{% if act.z > 5.0 %}
G0 X{min.x + 5.0} F{tl.speed.travel|int * 60}
G0 X{(max.x-min.x)/2}
G4 P{tl.park.time|float * 1000}
_TIMELAPSE_NEW_FRAME HYPERLAPSE=FALSE
G0 X{max.x - 5.0}
{% else %}
{action_raise_error("Toolhead z %.3f to low. Please place head above z = 5.0" % act.z)}
{% endif %}