From 489c0024738ba1bbf323b7da42a152f2b0f1d0bc Mon Sep 17 00:00:00 2001 From: Ondrej Vlach Date: Mon, 11 Mar 2024 18:32:53 +0100 Subject: [PATCH] initial commit --- calibrate_flow.cfg | 265 ++++++++++++++++++++++++++++ crowsnest.conf | 43 +++++ draw.cfg | 10 ++ mainsail.cfg | 242 ++++++++++++++++++++++++++ plate-zrnity.cfg | 5 + printer.cfg | 259 +++++++++++++++++++++++++++ sonar.conf | 17 ++ timelapse.cfg | 424 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 1265 insertions(+) create mode 100644 calibrate_flow.cfg create mode 100644 crowsnest.conf create mode 100644 draw.cfg create mode 100644 mainsail.cfg create mode 100644 plate-zrnity.cfg create mode 100644 printer.cfg create mode 100644 sonar.conf create mode 100644 timelapse.cfg diff --git a/calibrate_flow.cfg b/calibrate_flow.cfg new file mode 100644 index 0000000..871f28f --- /dev/null +++ b/calibrate_flow.cfg @@ -0,0 +1,265 @@ +######################################### +###### FLOW MULTIPLIER CALIBRATION ###### +######################################### +# Written by Frix_x#0161 # +# @version: 1.6 + +# CHANGELOG: +# v1.6: directly added the [gcode_arcs] definition in this file to simplify installation +# v1.5: moved the install notes into a proper markdown file in: docs > features > flow_calibration.md +# v1.4: fix issue when extrude_factor is != 1 +# v1.3: fix the logging +# v1.2: fix for those using absolute extrusion that leads to an error +# v1.1: added part cooling fan control and some speed optimizations +# v1.0: first flow calibration macro + +# ------------------------------------------------------------------------------------------------------------------------- +# If you want to use it into your own config, please install it as a standalone macro as described in the +# installation section of this file: docs > features > flow_calibration.md +# ------------------------------------------------------------------------------------------------------------------------- + +### What is it ? ### +# The main reason for this set of macros is to get a filament and slicer agnostic way to calibrate the flow extrusion multiplier. +# The goal is to make it easy to set, share and use it. + +# This macro is parametric and most of the values can be adjusted with their respective input parameters. +# It can be called without any parameters - in which case the default values would be used - or with any combination of parameters as desired. + +# Feel free to ping me on Discord (Frix_x#0161) if you need help or have any comments to improve it :) + + +# =========================================================================================================== +# DO NOT MODIFY THOSE VARIABLES (they are used internaly by the flow calibration macro) +[gcode_macro _FLOW_CALIB_VARIABLES] +variable_last_shell_thickness: 0.0 +variable_last_evalue: 0.0 +gcode: + +[gcode_arcs] +resolution: 0.1 + +[gcode_macro FLOW_MULTIPLIER_CALIBRATION] +description: Print a small tower to calibrate the extrusion flow multiplier by measuring the shell +gcode: + # + # PARAMETERS + # + {% set do_raft = params.DO_RAFT|default(1)|int %} # whether to print a raft or not + {% set do_retract = params.DO_RECTRACT|default(0)|int %} # whether to enable retract/unrectract on travel moves + {% set print_size = params.PRINT_SIZE|default(40)|int %} # size of the printed object on the build plate + {% set print_height = params.HEIGHT|default(15)|int %} # height of the printed object + {% set corner_radius = params.CORNER_RADIUS|default(8)|int %} # radius of the corners to smooth the shell and toolpath + {% set number_of_perimeters = params.PERIMETERS|default(2)|int %} # number of perimeters to print the shell + {% set fan_speed = params.FAN_SPEED|default(20)|int %} # part cooling fan speed in percent (0-100) + + {% set e_multiplier = params.EXTRUSION_MULTIPLIER|default(1.00)|float %} # extrusion multiplier for the shell + {% set filament_diameter = params.FILAMENT_DIAMETER|default(1.75)|float %} # filament diameter + {% set extrusion_width = params.EXTRUSION_WIDTH|default(0.4)|float %} # extrusion width goal for one line + {% set layer_height = params.LAYER_HEIGHT|default(0.2)|float %} # layer height for the print + + {% set retract_length = params.RETRACT_LENGTH|default(0.5)|float %} # how much to retract when traveling between print moves + {% set initial_purge = params.PURGE_MM|default(1)|int %} # mm of filament to purge before printing. set to 0 to disable + {% set z_hop_height = 2 * layer_height %} + + {% set feedrate_print = params.CONTROL_SPEED|default(100)|int * 60 %} # print feedrate + {% set feedrate_travel = params.TRAVEL_SPEED|default(200)|int * 60 %} # travel feedrate between print moves + {% set feedrate_raft = params.RAFT_SPEED|default(60)|int * 60 %} # print feedrate for printing raft + {% set feedrate_z = params.Z_LIFT_SPEED|default(20)|int * 60 %} # z axis travel feedrate + {% set feedrate_retract = params.RETRACT_SPEED|default(50)|int * 60 %} # retract and deretract feedrate + + # + # COMPUTED VALUES + # + {% set e_per_mm = ((extrusion_width - layer_height) * layer_height + 3.14159 * (layer_height / 2)**2) / (3.14159 * (filament_diameter / 2)**2) %} # computed E factor (similar to Slic3r/PrusaSlicer/SuperSlicer) + {% set spacing = extrusion_width - layer_height * (1 - 3.14159 / 4) %} # line spacing during the print + {% set shell_thickness = extrusion_width + (number_of_perimeters|float - 1) * spacing %} # theoric shell thickness + + {% set max_x = printer.toolhead.axis_maximum.x|float %} + {% set max_y = printer.toolhead.axis_maximum.y|float %} + {% set x_start = max_x / 2 - print_size / 2 %} + {% set y_start = max_y / 2 - print_size / 2 %} + {% set x_end = x_start + print_size %} + {% set y_end = y_start + print_size %} + + {% set num_raft_lines = ([print_size, max_x]|min / spacing)|round(0, 'floor')|int %} + {% set raft_size = num_raft_lines * spacing %} + + # + # STARTING... + # + {action_respond_info("")} + {action_respond_info("Starting extrusion flow calibration print")} + {action_respond_info("This operation can not be interrupted by normal means. Hit the \"emergency stop\" button to stop it if needed")} + {action_respond_info("")} + {action_respond_info("Exrusion multiplier used: %.4f" % e_multiplier)} + {action_respond_info("Number of perimeters to print: %d" % number_of_perimeters)} + {action_respond_info("THEORIC SHELL THICKNESS: %.4f" % shell_thickness)} + {action_respond_info("")} + {action_respond_info("Measure the shell thickness using a caliper or micrometer. Then call the computation macro with the measured value:")} + {action_respond_info("COMPUTE_FLOW_MULTIPLIER MEASURED_THICKNESS=xxx.xxx")} + {action_respond_info("")} + + SAVE_GCODE_STATE NAME=STATE_FLOW_MULTIPLIER_CALIBRATION + + # + # set variables for later computation + # + SET_GCODE_VARIABLE MACRO=_FLOW_CALIB_VARIABLES VARIABLE=last_shell_thickness VALUE={shell_thickness} + SET_GCODE_VARIABLE MACRO=_FLOW_CALIB_VARIABLES VARIABLE=last_evalue VALUE={e_multiplier} + + # + # purging before raft + # + G90 + M83 + G92 E0.0 + G0 X{x_start} Y{y_start - 5} Z{layer_height} F{feedrate_travel} # move at the start position to do a purge line + + G91 # use relative coordinates for the prime line + G1 E{initial_purge} F{5 * 60} + G1 X{raft_size} E{raft_size * e_per_mm * 1.5} F{feedrate_raft / 2} # print prime line + G1 Y-{extrusion_width} E{extrusion_width * e_per_mm} F{feedrate_raft / 2} # move to next line + G1 X-{raft_size} E{raft_size * e_per_mm} F{feedrate_raft / 2} # print second prime line + + G1 E-{retract_length} F{feedrate_retract} # retract + G0 Z{z_hop_height} F{feedrate_z} # z-hop + + G90 # back to absolute coordinates + G0 X{x_start} Y{y_start} F{feedrate_travel} # move to start position + G1 Z{layer_height} F{feedrate_z} # move to print height + G1 E{retract_length} F{feedrate_retract} # unretract + + # set extrude_factor + M221 S{e_multiplier * 100} + + # + # print the raft + # + {% if do_raft == 1 %} + G91 # use relative coordinates for the raft + {% for curr_raft_line in range(1, num_raft_lines + 2) %} + # print a raft line with alternating direction + G1 Y{loop.cycle(1.0, -1.0) * raft_size} E{raft_size * e_per_mm} F{feedrate_raft} + + # spacing move + {% if not loop.last %} + G1 X{spacing} E{spacing * e_per_mm} F{feedrate_raft} + {% endif %} + {% endfor %} + + G1 E-{retract_length} F{feedrate_retract} # retract + G0 Z{z_hop_height} F{feedrate_z} # z-hop + G90 # back to absolute coordinates + {% endif %} + + # + # print the shell + # + G90 + M106 S{fan_speed * 255 / 100} + + # for each layer + {% for curr_layer in range(1, (print_height / layer_height)|round|int) %} + G0 X{x_start + corner_radius} Y{y_start} F{feedrate_travel} # move to XY start position + G1 Z{(curr_layer * layer_height) + (layer_height if do_raft == 1 else 0)} F{feedrate_z} # move to Z start position + + # print one layer of the shell (in a for loop to do all the perimeters of one layer) + {% for perim_num in range(number_of_perimeters) %} + # compute values for the current perimeter (offset and radius) + {% set perim_offset = perim_num * spacing %} + {% set perim_radius = corner_radius - (perim_num * spacing) %} + + # start position of the current perimeter + G1 X{x_start + corner_radius} Y{y_start + perim_offset} F{feedrate_travel} + {% if do_retract == 1 %} + G1 E{retract_length} F{feedrate_retract} # unretract + {% endif %} + + # print the perimeter using the offset and radius computed + G1 X{x_end - corner_radius} Y{y_start + perim_offset} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print} + G3 X{x_end - perim_offset} Y{y_start + corner_radius} J{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print} + G1 X{x_end - perim_offset} Y{y_end - corner_radius} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print} + G3 X{x_end - corner_radius} Y{y_end - perim_offset} I-{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print} + G1 X{x_start + corner_radius} Y{y_end - perim_offset} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print} + G3 X{x_start + perim_offset} Y{y_end - corner_radius} J-{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print} + G1 X{x_start + perim_offset} Y{y_start + corner_radius} E{(print_size - (2 * corner_radius)) * e_per_mm} F{feedrate_print} + G3 X{x_start + corner_radius} Y{y_start + perim_offset} I{perim_radius} E{(3.14159 / 2) * perim_radius * e_per_mm} F{feedrate_print} + + {% if do_retract == 1 %} + G1 E-{retract_length} F{feedrate_retract} # retract + {% endif %} + {% endfor %} + + {% if do_retract == 1 %} + G91 + G0 Z{z_hop_height} F{feedrate_z} + G90 + {% endif %} + {% endfor %} + + # + # retract and move away + # + G1 E-{retract_length} F{feedrate_retract} + G91 + G0 Z20 F{feedrate_travel} + + RESTORE_GCODE_STATE NAME=STATE_FLOW_MULTIPLIER_CALIBRATION + + +[gcode_macro COMPUTE_FLOW_MULTIPLIER] +description: Compute a new flow multiplier by using the measured shell thickness on the calibration print +gcode: + {% set evalue = params.OLD_EXTRUSION_MULTIPLIER|default(0.0)|float %} # extrusion multiplier used for the calibration print + {% set theorical_thickness = params.THEORICAL_THICKNESS|default(0.0)|float %} # theorical shell thickness + {% set measured_thickness = params.MEASURED_THICKNESS|default(0.0)|float %} # measured shell thickness on the calibration print + + # if there is no OLD_EXTRUSION_MULTIPLIER passed as param, get the one from the last print calib run + {% if evalue == 0.0 %} + {% set last_evalue = printer["gcode_macro _FLOW_CALIB_VARIABLES"].last_evalue %} + + # then, if there is also no evalue saved from the last run, alert user + {% if last_evalue == 0.0 %} + {action_respond_info("It seems that no calibration print was run prior to this (or a restart of Klipper occured).")} + {action_respond_info("You can still manually use it by calling again this macro like that:")} + {action_respond_info("COMPUTE_FLOW_MULTIPLIER OLD_EXTRUSION_MULTIPLIER=xxx.xxx THEORICAL_THICKNESS=xxx.xxx MEASURED_THICKNESS=xxx.xxx")} + {action_raise_error("not enough data to perform the computation of the new flow !")} + {% else %} + {% set final_evalue = last_evalue %} + {action_respond_info("Using OLD_EXTRUSION_MULTIPLIER: %.3f" % final_evalue)} + {% endif %} + {% else %} + {% set final_evalue = evalue %} + {action_respond_info("Using OLD_EXTRUSION_MULTIPLIER: %.3f" % final_evalue)} + {% endif %} + + # similarly, if there is no THEORICAL_THICKNESS passed as param, get the one from the last print calib run + {% if theorical_thickness == 0.0 %} + {% set last_shell_thickness = printer["gcode_macro _FLOW_CALIB_VARIABLES"].last_shell_thickness %} + + # then, if there is also no evalue saved from the last run, alert user + {% if last_shell_thickness == 0.0 %} + {action_respond_info("It seems that no calibration print was run prior to this (or a restart of Klipper occured).")} + {action_respond_info("You can still manually use it by calling again this macro like that:")} + {action_respond_info("COMPUTE_FLOW_MULTIPLIER OLD_EXTRUSION_MULTIPLIER=xxx.xxx THEORICAL_THICKNESS=xxx.xxx MEASURED_THICKNESS=xxx.xxx")} + {action_raise_error("not enough data to perform the computation of the new flow !")} + {% else %} + {% set final_theorical_thickness = last_shell_thickness %} + {action_respond_info("Using THEORICAL_THICKNESS: %.3f" % final_theorical_thickness)} + {% endif %} + {% else %} + {% set final_theorical_thickness = theorical_thickness %} + {action_respond_info("Using THEORICAL_THICKNESS: %.3f" % final_theorical_thickness)} + {% endif %} + + # use the measured thickness from the user to compute a new flow value + {% if measured_thickness == 0.0 %} + {action_respond_info("You must use a caliper or micrometer to measure the calibration print shell thickness and call this macro with the measured value !!!")} + {action_respond_info("COMPUTE_FLOW_MULTIPLIER MEASURED_THICKNESS=xxx.xxx")} + {action_raise_error("not enough data to perform the computation of the new flow !")} + {% else %} + {% set new_evalue = final_theorical_thickness * final_evalue / measured_thickness %} + {action_respond_info("NEW COMPUTED FLOW VALUE: %.3f" % new_evalue)} + {action_respond_info("Use this new value as extrusion multiplier in your slicer of choice")} + {action_respond_info("")} + {% endif %} diff --git a/crowsnest.conf b/crowsnest.conf new file mode 100644 index 0000000..64b6a7f --- /dev/null +++ b/crowsnest.conf @@ -0,0 +1,43 @@ +#### crowsnest.conf +#### This is a typical default config. +#### Also used as default in mainsail / MainsailOS +#### See: +#### https://github.com/mainsail-crew/crowsnest/blob/master/README.md +#### for details to configure to your needs. + + +##################################################################### +#### ##### +#### Information about ports and according URL's ##### +#### ##### +##################################################################### +#### ##### +#### Port 8080 equals /webcam/?action=[stream/snapshot] ##### +#### Port 8081 equals /webcam2/?action=[stream/snapshot] ##### +#### Port 8082 equals /webcam3/?action=[stream/snapshot] ##### +#### Port 8083 equals /webcam4/?action=[stream/snapshot] ##### +#### ##### +##################################################################### +#### RTSP Stream URL: ( if enabled and supported ) ##### +#### rtsp://:/stream.h264 ##### +##################################################################### + + +[crowsnest] +log_path: /home/pi/printer_data/logs/crowsnest.log +log_level: verbose # Valid Options are quiet/verbose/debug +delete_log: false # Deletes log on every restart, if set to true +no_proxy: false + +[cam 1] +mode: camera-streamer # ustreamer - Provides mjpg and snapshots. (All devices) + # camera-streamer - Provides webrtc, mjpg and snapshots. (rpi + Raspi OS based only) +enable_rtsp: false # If camera-streamer is used, this enables also usage of an rtsp server +rtsp_port: 8554 # Set different ports for each device! +port: 8080 # HTTP/MJPG Stream/Snapshot Port +device: /dev/video0 # See Log for available ... +resolution: 1920x1080 # widthxheight format +max_fps: 15 # If Hardware Supports this it will be forced, otherwise ignored/coerced. +custom_flags: --camera-path=/base/soc/i2c0mux/i2c@1/ov5647@36 --camera-type=libcamera --camera-format=H264 --camera-nbufs=3 --camera-fps=30 --camera-allow_dma=1 --camera-high_res_factor=0.500000 --camera-low_res_factor=0.500000 --camera-auto_reconnect=0 --camera-auto_focus=1 --camera-vflip=0 --camera-hflip=0 --camera-snapshot.options=compression_quality=100 --camera-snapshot.height=0 --camera-stream.disabled=0 --camera-stream.options=compression_quality=100 --camera-stream.height=0 --camera-stream.disabled=0 --camera-stream.options=video_bitrate_mode=0 --camera-stream.options=repeat_sequence_header=5000000 --camera-stream.options=h264_i_frame_period=30 --camera-stream.options=h264_level=11 --camera-stream.options=h264_profile=4 --camera-stream.options=Sharpness=0.0 --camera-stream.options=ExposureValue=0 --camera-stream.options=h264_minimum_qp_value=51 --camera-stream.options=h264_maximum_qp_value=51 --camera-stream.options=video_bitrate=25000000 --camera-stream.options=video_bitrate_mode=0 --camera-stream.options=AeExposureMode=2 --camera-stream.options=ScalerCrop=0 --camera-list_options=0 +# You can run the Stream Services with custom flags. +#v4l2ctl: # Add v4l2-ctl parameters to setup your camera, see Log what your cam is capable of. diff --git a/draw.cfg b/draw.cfg new file mode 100644 index 0000000..d2e1354 --- /dev/null +++ b/draw.cfg @@ -0,0 +1,10 @@ + +[gcode_macro draw_purge_line] +gcode: + G92 E0 + G1 X0.4 Y-0.5 Z0.3 F5000.0 ; Move to side a little + G1 X100 Y-0.5 Z0.3 F1500.0 E15 ; Draw the first line + G1 X0.4 Y-0.5 Z0.3 F5000.0 ; Move to side a little + G1 X100 Y-0.5 Z0.3 F1500.0 E30 ; Draw the second line + G1 X200 Y-0.5 Z0.3 F700.0 ; Move to side a little + G92 E0 ; Reset Extruder \ No newline at end of file diff --git a/mainsail.cfg b/mainsail.cfg new file mode 100644 index 0000000..bc0541b --- /dev/null +++ b/mainsail.cfg @@ -0,0 +1,242 @@ +## Client klipper macro definitions +## +## Copyright (C) 2022 Alex Zellner +## +## This file may be distributed under the terms of the GNU GPLv3 license +## +## !!! This file is read-only. Maybe the used editor indicates that. !!! +## +## Customization: +## 1) copy the gcode_macro _CLIENT_VARIABLE (see below) to your printer.cfg +## 2) remove the comment mark (#) from all lines +## 3) change any value in there to your needs +## +## Use the PAUSE macro direct in your M600: +## e.g. with a different park position front left and a minimal height of 50 +## [gcode_macro M600] +## description: Filament change +## gcode: PAUSE X=10 Y=10 Z_MIN=50 +## Z_MIN will park the toolhead at a minimum of 50 mm above to bed to make it easier for you to swap filament. +## +## Client variable macro for your printer.cfg +#[gcode_macro _CLIENT_VARIABLE] +#variable_use_custom_pos : False ; use custom park coordinates for x,y [True/False] +#variable_custom_park_x : 0.0 ; custom x position; value must be within your defined min and max of X +#variable_custom_park_y : 0.0 ; custom y position; value must be within your defined min and max of Y +#variable_custom_park_dz : 2.0 ; custom dz value; the value in mm to lift the nozzle when move to park position +#variable_retract : 1.0 ; the value to retract while PAUSE +#variable_cancel_retract : 5.0 ; the value to retract while CANCEL_PRINT +#variable_speed_retract : 35.0 ; retract speed in mm/s +#variable_unretract : 1.0 ; the value to unretract while RESUME +#variable_speed_unretract : 35.0 ; unretract speed in mm/s +#variable_speed_hop : 15.0 ; z move speed in mm/s +#variable_speed_move : 100.0 ; move speed in mm/s +#variable_park_at_cancel : False ; allow to move the toolhead to park while execute CANCEL_PRINT [True/False] +#variable_park_at_cancel_x : None ; different park position during CANCEL_PRINT [None/Position as Float]; park_at_cancel must be True +#variable_park_at_cancel_y : None ; different park position during CANCEL_PRINT [None/Position as Float]; park_at_cancel must be True +## !!! Caution [firmware_retraction] must be defined in the printer.cfg if you set use_fw_retract: True !!! +#variable_use_fw_retract : False ; use fw_retraction instead of the manual version [True/False] +#gcode: + +[virtual_sdcard] +path: ~/printer_data/gcodes +on_error_gcode: CANCEL_PRINT + +[pause_resume] + +[display_status] + +[gcode_macro CANCEL_PRINT] +description: Cancel the actual running print +rename_existing: CANCEL_PRINT_BASE +gcode: + ##### get user parameters or use default ##### + {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %} + {% set allow_park = False if not macro_found + else False if client.park_at_cancel is not defined + else True if client.park_at_cancel|lower == 'true' + else False %} + {% set retract = 5.0 if not macro_found else client.cancel_retract|default(5.0)|abs %} + ##### define park position ##### + {% set park_x = "" if not macro_found + else "" if client.park_at_cancel_x is not defined + else "X=" + client.park_at_cancel_x|string if client.park_at_cancel_x is not none %} + {% set park_y = "" if not macro_found + else "" if client.park_at_cancel_y is not defined + else "Y=" + client.park_at_cancel_y|string if client.park_at_cancel_y is not none %} + {% set custom_park = True if (park_x|length > 0 or park_y|length > 0) else False %} + ##### end of definitions ##### + {% if (custom_park or not printer.pause_resume.is_paused) and allow_park %} _TOOLHEAD_PARK_PAUSE_CANCEL {park_x} {park_y} {% endif %} + _CLIENT_RETRACT LENGTH={retract} + TURN_OFF_HEATERS + M106 S0 + # clear pause_next_layer and pause_at_layer as preparation for next print + SET_PAUSE_NEXT_LAYER ENABLE=0 + SET_PAUSE_AT_LAYER ENABLE=0 LAYER=0 + CANCEL_PRINT_BASE + +[gcode_macro PAUSE] +description: Pause the actual running print +rename_existing: PAUSE_BASE +gcode: + SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=last_extruder_temp VALUE="{printer[printer.toolhead.extruder].target}" + + PAUSE_BASE + _TOOLHEAD_PARK_PAUSE_CANCEL {rawparams} + +[gcode_macro RESUME] +description: Resume the actual running print +rename_existing: RESUME_BASE +variable_last_extruder_temp: 0 +gcode: + ##### get user parameters or use default ##### + {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %} + {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %} + {% set sp_move = velocity if not macro_found else client.speed_move|default(velocity) %} + ##### end of definitions ##### + M109 S{last_extruder_temp} + + _CLIENT_EXTRUDE + RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)} + +# Usage: SET_PAUSE_NEXT_LAYER [ENABLE=[0|1]] [MACRO=] +[gcode_macro SET_PAUSE_NEXT_LAYER] +description: Enable a pause if the next layer is reached +gcode: + {% set pause_next_layer = printer['gcode_macro SET_PRINT_STATS_INFO'].pause_next_layer %} + {% set ENABLE = params.ENABLE | default(1) | int != 0 %} + {% set MACRO = params.MACRO | default(pause_next_layer.call, True) %} + SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_next_layer VALUE="{{ 'enable': ENABLE, 'call': MACRO }}" + +# Usage: SET_PAUSE_AT_LAYER [ENABLE=[0|1]] [LAYER=] [MACRO=] +[gcode_macro SET_PAUSE_AT_LAYER] +description: Enable/disable a pause if a given layer number is reached +gcode: + {% set pause_at_layer = printer['gcode_macro SET_PRINT_STATS_INFO'].pause_at_layer %} + {% set ENABLE = params.ENABLE | int != 0 if params.ENABLE is defined + else params.LAYER is defined %} + {% set LAYER = params.LAYER | default(pause_at_layer.layer) | int %} + {% set MACRO = params.MACRO | default(pause_at_layer.call, True) %} + SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_at_layer VALUE="{{ 'enable': ENABLE, 'layer': LAYER, 'call': MACRO }}" + +# Usage: SET_PRINT_STATS_INFO [TOTAL_LAYER=] [CURRENT_LAYER= ] +[gcode_macro SET_PRINT_STATS_INFO] +rename_existing: SET_PRINT_STATS_INFO_BASE +description: Overwrite, to get pause_next_layer and pause_at_layer feature +variable_pause_next_layer: { 'enable': False, 'call': "PAUSE" } +variable_pause_at_layer : { 'enable': False, 'layer': 0, 'call': "PAUSE" } +gcode: + {% if pause_next_layer.enable %} + {action_respond_info("%s, forced by pause_next_layer" % pause_next_layer.call)} + {pause_next_layer.call} ; execute the given gcode to pause, should be either M600 or PAUSE + SET_PAUSE_NEXT_LAYER ENABLE=0 + {% elif pause_at_layer.enable and params.CURRENT_LAYER is defined and params.CURRENT_LAYER|int == pause_at_layer.layer %} + {action_respond_info("%s, forced by pause_at_layer [%d]" % (pause_at_layer.call, pause_at_layer.layer))} + {pause_at_layer.call} ; execute the given gcode to pause, should be either M600 or PAUSE + SET_PAUSE_AT_LAYER ENABLE=0 + {% endif %} + SET_PRINT_STATS_INFO_BASE {rawparams} + +##### internal use ##### +[gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL] +description: Helper: park toolhead used in PAUSE and CANCEL_PRINT +gcode: + ##### get user parameters or use default ##### + {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %} + {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %} + {% set use_custom = False if not macro_found + else False if client.use_custom_pos is not defined + else True if client.use_custom_pos|lower == 'true' + else False %} + {% set custom_park_x = 0.0 if not macro_found else client.custom_park_x|default(0.0) %} + {% set custom_park_y = 0.0 if not macro_found else client.custom_park_y|default(0.0) %} + {% set park_dz = 2.0 if not macro_found else client.custom_park_dz|default(2.0)|abs %} + {% set sp_hop = 900 if not macro_found else client.speed_hop|default(15) * 60 %} + {% set sp_move = velocity * 60 if not macro_found else client.speed_move|default(velocity) * 60 %} + ##### get config and toolhead values ##### + {% set origin = printer.gcode_move.homing_origin %} + {% set act = printer.gcode_move.gcode_position %} + {% set max = printer.toolhead.axis_maximum %} + {% set cone = printer.toolhead.cone_start_z|default(max.z) %} ; height as long the toolhead can reach max and min of an delta + {% set round_bed = True if printer.configfile.settings.printer.kinematics is in ['delta','polar','rotary_delta','winch'] + else False %} + ##### define park position ##### + {% set z_min = params.Z_MIN|default(0)|float %} + {% set z_park = [[(act.z + park_dz), z_min]|max, (max.z - origin.z)]|min %} + {% set x_park = params.X if params.X is defined + else custom_park_x if use_custom + else 0.0 if round_bed + else (max.x - 5.0) %} + {% set y_park = params.Y if params.Y is defined + else custom_park_y if use_custom + else (max.y - 5.0) if round_bed and z_park < cone + else 0.0 if round_bed + else (max.y - 5.0) %} + ##### end of definitions ##### + _CLIENT_RETRACT + {% if "xyz" in printer.toolhead.homed_axes %} + G90 + G1 Z{z_park} F{sp_hop} + G1 X{x_park} Y{y_park} F{sp_move} + {% if not printer.gcode_move.absolute_coordinates %} G91 {% endif %} + {% else %} + {action_respond_info("Printer not homed")} + {% endif %} + +[gcode_macro _CLIENT_EXTRUDE] +description: Extrudes, if the extruder is hot enough +gcode: + {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %} + {% set use_fw_retract = False if not macro_found + else False if client.use_fw_retract is not defined + else True if client.use_fw_retract|lower == 'true' and printer.firmware_retraction is defined + else False %} + + {% set length = (params.LENGTH|float) if params.LENGTH is defined + else 1.0 if not macro_found + else client.unretract|default(1.0) %} + + {% set speed = params.SPEED if params.SPEED is defined + else 35 if not macro_found + else client.speed_unretract|default(35) %} + + {% set absolute_extrude = printer.gcode_move.absolute_extrude %} + + {% if printer.extruder.can_extrude %} + {% if use_fw_retract %} + {% if length < 0 %} + G10 + {% else %} + G11 + {% endif %} + {% else %} + M83 + G1 E{length} F{(speed|float|abs) * 60} + {% if absolute_extrude %} + M82 + {% endif %} + {% endif %} + {% else %} + {action_respond_info("Extruder not hot enough")} + {% endif %} + +[gcode_macro _CLIENT_RETRACT] +description: Retracts, if the extruder is hot enough +gcode: + {% set macro_found = True if printer['gcode_macro _CLIENT_VARIABLE'] is defined else False %} + {% set client = printer['gcode_macro _CLIENT_VARIABLE'] %} + + {% set length = (params.LENGTH|float) if params.LENGTH is defined + else 1.0 if not macro_found + else client.retract|default(1.0) %} + + {% set speed = params.SPEED if params.SPEED is defined + else 35 if not macro_found + else client.speed_retract|default(35) %} + + _CLIENT_EXTRUDE LENGTH=-{length|float|abs} SPEED={speed|float|abs} + \ No newline at end of file diff --git a/plate-zrnity.cfg b/plate-zrnity.cfg new file mode 100644 index 0000000..5323037 --- /dev/null +++ b/plate-zrnity.cfg @@ -0,0 +1,5 @@ +[gcode_macro NAN_PLATE] +description: set correctly plate z offset +gcode: + SET_GCODE_OFFSET Z=0 + SET_GCODE_OFFSET Z=-0.690 \ No newline at end of file diff --git a/printer.cfg b/printer.cfg new file mode 100644 index 0000000..20f4e33 --- /dev/null +++ b/printer.cfg @@ -0,0 +1,259 @@ +## DO NOT EDIT THIS FILE, IT IS A TEMPLATE. THAT YOU NEED TO COPY +# Prusa MK3s Klipper Config + +# The first thing you'll need to do is go through this file and comment out / uncomment +# the files and/or settings you need. + +# You'll be able to print just fine with this config as it is, but it is recommended +# that you follow these steps to properly calibrate your printer: + +# 0) Sanity check and PID Tuning: https://www.klipper3d.org/Config_checks.html +# 1) Pressure Advance: https://www.klipper3d.org/Pressure_Advance.html +# 2) Skew Correction: https://www.klipper3d.org/skew_correction.html +# 3) Resonance Compensation: https://www.klipper3d.org/Resonance_Compensation.html + +# Read more about klipper here: https://www.klipper3d.org/Overview.html + +### UI +[include mainsail.cfg] +# [include fluidd.cfg] + +[mcu] +#serial: /dev/serial0 # If you are using internal RPI serial port +serial: /dev/ttyACM0 # If you are using RPI via USB connection to printer +restart_method: command + + +### CONTROL BOARD +[include klipper-prusa-mk3s/mk3s/einsy-rambo.cfg] + +### BASE SETUP +[include klipper-prusa-mk3s/mk3s/display.cfg] +[include klipper-prusa-mk3s/mk3s/steppers.cfg] +[include klipper-prusa-mk3s/mk3s/tmc2130.cfg] + +### EXTRUSION + +# Extruder +[include klipper-prusa-mk3s/extruders/prusa.cfg] +# [include klipper-prusa-mk3s/extruders/bmg.cfg] + +# Hotend +[include klipper-prusa-mk3s/hotends/v6.cfg] +# [include klipper-prusa-mk3s/hotends/dragon-standard-flow.cfg] +# [include klipper-prusa-mk3s/hotends/rapido.cfg] + +# flow calibrate +[include calibrate_flow.cfg] + +[extruder] +# To tune Pressure Advance see https://www.klipper3d.org/Pressure_Advance.html +# default is already set based on hotend, but you can further improve prints by calibrating it to your nozzle and material +# 0.06065 - 0.060700000000000004 +pressure_advance: 0.06065 +nozzle_diameter: 0.4 # Remember to change this if you change nozzle diameter. +pid_Kp: 20.457 +pid_Ki: 0.771 +pid_Kd: 135.785 + +[heater_bed] +pid_Kp: 49.052 +pid_Ki: 0.531 +pid_Kd: 1133.094 + +## copy this from your current setting on Prusa, but make it absolute (removing -) +[probe] +z_offset: 1.150 +samples: 3 +samples_tolerance_retries: 3 +samples_result: median + + +## For faster printing enable +[printer] +max_accel: 2000 +max_accel_to_decel: 2000 +max_z_velocity: 20 # TODO: Zvysit na 20/300 po utahnuti remenu +max_z_accel: 300 + +## For stealth mode enable + +# [tmc2130 stepper_x] +# interpolate: True +# stealthchop_threshold: 80 +# [tmc2130 stepper_y] +# interpolate: True +# stealthchop_threshold: 80 +# [tmc2130 stepper_z] +# interpolate: True +# stealthchop_threshold: 80 + +## Custom bed mest probes +## Prusa has 3x3 or 7x7, you can do any variation you want +[bed_mesh] +probe_count: 5,5 +horizontal_move_z: 4 + +# Linear correction +# Check `extruders/linear-correction` for more informations. +[include klipper-prusa-mk3s/extruders/linear-correction/linear-correction-0.cfg] # Default Prusa linear correction optimized for LDO motors + +### MACROS +[include klipper-prusa-mk3s/macros.cfg] + +[include plate-zrnity.cfg] + +[include draw.cfg] + +[screws_tilt_adjust] +screw1: 123,115 +screw1_name: Center Center + +screw2: 13,6 +screw2_name: Left Front +screw3: 13,115 +screw3_name: Left Center +screw4: 13,210 +screw4_name: Left Back + +screw5: 123,6 +screw5_name: Center Front +screw6: 123,210 +screw6_name: Center Back + + +# TODO: 228 right, but induction not work! +screw7: 215,6 +screw7_name: Right Front +screw8: 215,115 +screw8_name: Right Center +screw9: 215,210 +screw9_name: Right Back + +horizontal_move_z: 10. +speed: 50. +screw_thread: CW-M3 + +[gcode_macro PRINT_START] +gcode: + NAN_PLATE + {% set BED = params.BED|default(60)|float %} + {% set EXTRUDER = params.EXTRUDER|default(190)|float %} + {% set FLOW_RATIO = params.FLOW_RATIO|default(0.989)|float * 100 %} + # Start bed heating + M140 S{BED} + # Use absolute coordinates + G90 + # Reset the G-Code Z offset (adjust Z offset if needed) + #SET_GCODE_OFFSET Z=0.0 + # Home the printer + G28 + + # Move the nozzle near the bed + G1 Z5 F3000 + # Move the nozzle very close to the bed + G1 Z0.40 F300 + G80 + M221 S{FLOW_RATIO} + # Wait for bed to reach temperature + M190 S{BED} + # Set and wait for nozzle to reach temperature + M109 S{EXTRUDER} + DRAW_PURGE_LINE + +[gcode_macro PRINT_END] +gcode: + # Turn off bed, extruder, and fan + M140 S0 + M104 S0 + M106 S0 + # Move nozzle away from print while retracting + G91 + G1 X-2 Y-2 E-3 F300 + # Raise nozzle by 10mm + G1 Z10 F3000 + G90 + # Disable steppers + M84 + +[gcode_macro NAN_START_PRINT] +description: Start print macro +gcode: + NAN_TURN_ON_LEDS + +[gcode_macro NAN_END_PRINT] +description: End print macro +gcode: + UPDATE_DELAYED_GCODE ID=turn_off_leds DURATION=600 + UPDATE_DELAYED_GCODE ID=turn_off_enc_fan DURATION=600 + +[gcode_macro CHANGE_NOOZLE] +description: Change noozly +gcode: + NAN_TURN_ON_LEDS + M117 Change noozle + G28 + G0 X100 Y0 Z200 + UNLOAD_FILAMENT + RESPOND TYPE=command MSG="OK" + UPDATE_DELAYED_GCODE ID=clear_message DURATION=10 + UPDATE_DELAYED_GCODE ID=turn_off_leds DURATION=10 + +[delayed_gcode clear_message] +gcode: + M117 + +[delayed_gcode turn_off_leds] +gcode: + NAN_TURN_OFF_LEDS + +[delayed_gcode turn_off_enc_fan] +gcode: + NAN_SET_FAN_SPEED SPEED=0 + +[gcode_macro NAN_NLOAD_FILAMENT] +gcode: + SAVE_GCODE_STATE NAME=unload_state + G91 + {% if params.TEMP is defined or printer.extruder.can_extrude|lower == 'false' %} + M117 Heating... + # Heat up hotend to provided temp or 220 as default as that should work OK with most filaments. + M109 S{params.TEMP|default(220, true)} + {% endif %} + M117 Unloading filament... + G92 E0.0 + G91 + G1 E-45 F5000 + G1 E-15 F1000 + G1 E-20 F1000 + G1 E-20 F1000 + G90 + G92 E0.0 + M400 + M117 Remove Filament Now! + M300 S300 P1000 + M117 Filament unloaded! + RESTORE_GCODE_STATE NAME=unload_state + +#[fan_generic chamber_fan] +#pin: host:pwmchip0/pwm0 +#hardware_pwm: True + +#LEDS +[neopixel_client] + + +# FIRST RUN: +# Execute these sequentially in the console, let PID tuning finish before saving +# PID_CALIBRATE HEATER=extruder TARGET=170 +# SAVE_CONFIG +# PID_CALIBRATE HEATER=heater_bed TARGET=60 +# SAVE_CONFIG + +### The end, on the end the printer will store it's tuning data, so do not edit it. + +#*# <---------------------- SAVE_CONFIG ----------------------> +#*# DO NOT EDIT THIS BLOCK OR BELOW. The contents are auto-generated. +#*# +#*# [probe] +#*# z_offset = 2.500 diff --git a/sonar.conf b/sonar.conf new file mode 100644 index 0000000..0c71ab1 --- /dev/null +++ b/sonar.conf @@ -0,0 +1,17 @@ +#### Sonar - A WiFi Keepalive daemon +#### +#### Written by Stephan Wendel aka KwadFan +#### Copyright 2022 +#### https://github.com/mainsail-crew/sonar +#### +#### This File is distributed under GPLv3 +#### + +[sonar] +enable: false # false to disable till next reboot (will stop again if not set to true) +debug_log: false # if set to true, sonar will log ever ping with triptime and date/time +persistant_log: false # If true logs in /var/log/sonar.log, false logs to systemd +target: auto # IP Address, URL or auto as ping target +count: 3 # How often should be pinged? +interval: 60 # Ping again after X seconds +restart_treshold: 10 # If failed, restart WiFi after X seconds diff --git a/timelapse.cfg b/timelapse.cfg new file mode 100644 index 0000000..134243f --- /dev/null +++ b/timelapse.cfg @@ -0,0 +1,424 @@ +# Timelapse klipper macro definition +# +# Copyright (C) 2021 Christoph Frei +# Copyright (C) 2021 Alex Zellner +# +# This file may be distributed under the terms of the GNU GPLv3 license +# +# Macro version 1.14 +# + +##### 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 %} + {% set _dummy = output_txt.append("park position: %s time: %s s" % (tl.park.pos, tl.park.time)) %} + {% set _dummy = output_txt.append("park cord x:%s y:%s dz:%s" % (tl.park.coord.x, tl.park.coord.y, tl.park.coord.dz)) %} + {% 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 not tl.extruder.fw_retract %} + {% 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: + {% set tl = printer['gcode_macro TIMELAPSE_TAKE_FRAME'] %} + ##### get min and max bed size ##### + {% set min = printer.toolhead.axis_minimum %} + {% set max = printer.toolhead.axis_maximum %} + {% set round_bed = True if printer.configfile.settings.printer.kinematics is in ['delta','polar','rotary_delta','winch'] + else False %} + {% set park = {'min' : {'x': (min.x / 1.42)|round(3) if round_bed else min.x|round(3), + 'y': (min.y / 1.42)|round(3) if round_bed else min.y|round(3)}, + 'max' : {'x': (max.x / 1.42)|round(3) if round_bed else max.x|round(3), + 'y': (max.y / 1.42)|round(3) if round_bed else max.y|round(3)}, + 'center': {'x': (max.x-(max.x-min.x)/2)|round(3), + 'y': (max.y-(max.y-min.y)/2)|round(3)}} %} + ##### set new values ##### + {% if params.ENABLE %} + {% if params.ENABLE|lower is in ['true', 'false'] %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=enable VALUE={True if params.ENABLE|lower == 'true' else False} + {% else %} + {action_raise_error("ENABLE=%s not supported. Allowed values are [True, False]" % params.ENABLE|capitalize)} + {% endif %} + {% endif %} + {% if params.VERBOSE %} + {% if params.VERBOSE|lower is in ['true', 'false'] %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=verbose VALUE={True if params.VERBOSE|lower == 'true' else False} + {% else %} + {action_raise_error("VERBOSE=%s not supported. Allowed values are [True, False]" % params.VERBOSE|capitalize)} + {% endif %} + {% endif %} + {% if params.CUSTOM_POS_X %} + {% if params.CUSTOM_POS_X|float >= min.x and params.CUSTOM_POS_X|float <= max.x %} + {% set _dummy = tl.park.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 %} + {% if params.CUSTOM_POS_Y|float >= min.y and params.CUSTOM_POS_Y|float <= max.y %} + {% set _dummy = tl.park.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 %} + {% if params.CUSTOM_POS_DZ|float >= min.z and params.CUSTOM_POS_DZ|float <= max.z %} + {% set _dummy = tl.park.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.PARK_ENABLE %} + {% if params.PARK_ENABLE|lower is in ['true', 'false'] %} + {% set _dummy = tl.park.update({'enable':True if params.PARK_ENABLE|lower == 'true' else False}) %} + {% else %} + {action_raise_error("PARK_ENABLE=%s not supported. Allowed values are [True, False]" % params.PARK_ENABLE|capitalize)} + {% endif %} + {% endif %} + {% if params.PARK_POS %} + {% if params.PARK_POS|lower is in ['center','front_left','front_right','back_left','back_right','custom','x_only','y_only'] %} + {% set dic = {'center' : {'x': park.center.x , 'y': park.center.y , 'dz': 1 }, + 'front_left' : {'x': park.min.x , 'y': park.min.y , 'dz': 0 }, + 'front_right' : {'x': park.max.x , 'y': park.min.y , 'dz': 0 }, + 'back_left' : {'x': park.min.x , 'y': park.max.y , 'dz': 0 }, + 'back_right' : {'x': park.max.x , 'y': park.max.y , 'dz': 0 }, + 'custom' : {'x': tl.park.custom.x, 'y': tl.park.custom.y, 'dz': tl.park.custom.dz}, + 'x_only' : {'x': tl.park.custom.x, 'y': 'none' , 'dz': tl.park.custom.dz}, + 'y_only' : {'x': 'none' , 'y': tl.park.custom.y, 'dz': tl.park.custom.dz}} %} + {% set _dummy = tl.park.update({'pos':params.PARK_POS|lower}) %} + {% set _dummy = tl.park.update({'coord':dic[tl.park.pos]}) %} + {% else %} + {action_raise_error("PARK_POS=%s not supported. Allowed values are [CENTER, FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, CUSTOM, X_ONLY, Y_ONLY]" + % params.PARK_POS|upper)} + {% endif %} + {% endif %} + {% if params.PARK_TIME %} + {% if params.PARK_TIME|float >= 0.0 %} + {% set _dummy = tl.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 %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=park VALUE="{tl.park}" + {% if params.TRAVEL_SPEED %} + {% if params.TRAVEL_SPEED|float > 0.0 %} + {% set _dummy = tl.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 %} + {% if params.RETRACT_SPEED|float > 0.0 %} + {% set _dummy = tl.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 %} + {% if params.EXTRUDE_SPEED|float > 0.0 %} + {% set _dummy = tl.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 %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=speed VALUE="{tl.speed}" + {% if params.EXTRUDE_DISTANCE %} + {% if params.EXTRUDE_DISTANCE|float >= 0.0 %} + {% set _dummy = tl.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 %} + {% if params.RETRACT_DISTANCE|float >= 0.0 %} + {% set _dummy = tl.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 %} + {% if params.FW_RETRACT|lower is in ['true', 'false'] %} + {% if 'firmware_retraction' in printer.configfile.settings %} + {% set _dummy = tl.extruder.update({'fw_retract': True if params.FW_RETRACT|lower == 'true' else False}) %} + {% else %} + {% set _dummy = tl.extruder.update({'fw_retract':False}) %} + {% if params.FW_RETRACT|capitalize == 'True' %} + {action_raise_error("[firmware_retraction] not defined in printer.cfg. Can not enable fw_retract")} + {% endif %} + {% endif %} + {% else %} + {action_raise_error("FW_RETRACT=%s not supported. Allowed values are [True, False]" % params.FW_RETRACT|capitalize)} + {% endif %} + {% endif %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=extruder VALUE="{tl.extruder}" + {% if printer.configfile.settings['gcode_macro pause'] is defined %} + {% set _dummy = tl.macro.update({'pause': printer.configfile.settings['gcode_macro pause'].rename_existing}) %} + {% endif %} + {% if printer.configfile.settings['gcode_macro resume'] is defined %} + {% set _dummy = tl.macro.update({'resume': printer.configfile.settings['gcode_macro resume'].rename_existing}) %} + {% endif %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=macro VALUE="{tl.macro}" + +########################################################################## +# # +# 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, x_only, y_only] +## park.time : used for the debug macro. Time in s +## park.custom.x, park.custom.y: coordinates of the custom parkposition. Unit [mm] +## park.custom.dz : custom z hop for the picture. Unit [mm] +## park.coord : internal use +## +## 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 +## restore.factor.speed : internal use +## restore.factor.extrude : internal use +## +## macro.pause : internal use +## macro.resume : 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, + 'custom': {'x': 0, 'y': 0, 'dz': 0}, + 'coord' : {'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, 'factor': {'speed': 1.0, 'extrude': 1.0}} +variable_macro: {'pause': 'PAUSE', 'resume': 'RESUME'} +variable_is_paused: False +gcode: + {% set hyperlapse = True if params.HYPERLAPSE and params.HYPERLAPSE|lower =='true' else False %} + {% if enable %} + {% if (hyperlapse and printer['gcode_macro HYPERLAPSE'].run) or + (not hyperlapse and not printer['gcode_macro HYPERLAPSE'].run) %} + {% if park.enable %} + {% set pos = {'x': 'X' + park.coord.x|string if park.pos != 'y_only' else '', + 'y': 'Y' + park.coord.y|string if park.pos != 'x_only' else '', + 'z': 'Z'+ [printer.gcode_move.gcode_position.z + park.coord.dz, printer.toolhead.axis_maximum.z]|min|string} %} + {% 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, + 'factor' : {'speed' : printer.gcode_move.speed_factor, + 'extrude': printer.gcode_move.extrude_factor}} %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=restore VALUE="{restore}" + {% if not printer[printer.toolhead.extruder].can_extrude %} + {% if verbose %}{action_respond_info("Timelapse: Warning, minimum extruder temperature not reached!")}{% endif %} + {% else %} + {% if extruder.fw_retract %} + G10 + {% else %} + M83 ; insure relative extrusion + G0 E-{extruder.retract} F{speed.retract * 60} + {% endif %} + {% endif %} + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=is_paused VALUE=True + {macro.pause} ; execute the klipper PAUSE command + SET_GCODE_OFFSET X=0 Y=0 ; this will insure that the head parks always at the same position in a multi setup + G90 ; insure absolute move + {% if "xyz" not in printer.toolhead.homed_axes %} + {% if verbose %}{action_respond_info("Timelapse: Warning, axis not homed yet!")}{% endif %} + {% else %} + G0 {pos.x} {pos.y} {pos.z} F{speed.travel * 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 %}{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'] %} + {% set factor = {'speed': printer.gcode_move.speed_factor, 'extrude': printer.gcode_move.extrude_factor} %} + {% if tl.takingframe %} + UPDATE_DELAYED_GCODE ID=_WAIT_TIMELAPSE_TAKE_FRAME DURATION=0.5 + {% else %} + {tl.macro.resume} VELOCITY={tl.speed.travel} ; execute the klipper RESUME command + SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=is_paused VALUE=False + {% if not printer[printer.toolhead.extruder].can_extrude %} + {action_respond_info("Timelapse: Warning minimum extruder temperature not reached!")} + {% else %} + {% if tl.extruder.fw_retract %} + G11 + {% else %} + G0 E{tl.extruder.extrude} F{tl.speed.extrude * 60} + G0 F{tl.restore.speed} + {% if tl.restore.absolute.extrude %} + M82 + G92 E{tl.restore.e} + {% endif %} + {% endif %} + {% endif %} + {% if tl.restore.factor.speed != factor.speed %} M220 S{(factor.speed*100)|round(0)} {% endif %} + {% if tl.restore.factor.extrude != factor.extrude %} M221 S{(factor.extrude*100)|round(0)} {% endif %} + {% if not tl.restore.absolute.coordinates %} 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 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 and params.ACTION|lower == 'stop' %} + {% if run %}{action_respond_info("Hyperlapse: frames stopped")}{% endif %} + SET_GCODE_VARIABLE MACRO=HYPERLAPSE VARIABLE=run VALUE=False + UPDATE_DELAYED_GCODE ID=_HYPERLAPSE_LOOP DURATION=0 + {% else %} + {action_raise_error("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 % 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 %}