Compare commits

..
2 Commits
Author SHA1 Message Date
mangavalkandClaude Opus 5.5 6cc43f951d Print start: soak before QGL and Z, load after Z, PA per lane temperature
PRINT_WARMUP: bed heats during the warmup, the nozzle only waits while it
is above 170C (Beacon contact limit 180C), one HOME to get over the bed,
then M190 and HEAT_SOAK. No more filament load and 220->150C cycle there.

PRINT_START (on the soaked bed): one QGL, one contact Z calibration, mesh,
heat over the bucket, load the initial tool, PA for all lanes, load the
initial tool again if a calibration changed lanes, G28 X Y reference.
Loading after the contact keeps ooze off the nozzle for the calibration.

PA: calibrate each lane at its own filament temperature (was the
temperature from before CHANGE_TOOL), and apply the loaded lane's PA
after PA_CALIBRATE_ALL_LANES (the last cached lane's PA won before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:46:05 +02:00
mangavalkandClaude Opus 5.5 e5be65834e LEDs: nozzle light follows the motion sensor, new logo status macro
The motion timeout switched the nozzle LEDs off during prints, motion
switched them off when idle or paused, the timeout counted from the first
movement, and every _status_* macro stopped the nozzle light.

- _LIGHTS sets case light and nozzle LEDs from presence, print state and
  CASELIGHT MODE=AUTO|ON|OFF; the timeout (60 s) starts at the sensor
  release
- _STATUS STATE=... replaces the _status_* macros; logo effects only
  cover the logo LEDs and use REPLACE=1
- heater gauge while heating, print progress, paused, error flash from
  _ERROR, part ready once the bed is cool, dim night mode when idle and
  nobody near, cleaning during BLOBIFIER_CLEAN
- removed unused effects and macros, 12 fps for the toolhead effects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:32:42 +02:00
9 changed files with 362 additions and 407 deletions

No files matched your search

+2 -2
View File
@@ -42,9 +42,9 @@ everything below, grouped by topic. Comment out what you do not use there.
| **spoolman/** | | |
| `active_spool.cfg` | `SET_ACTIVE_SPOOL`, `CLEAR_ACTIVE_SPOOL` | Spoolman in Moonraker |
| **leds/** | | |
| `stealthburner_leds.cfg` | Stealthburner LED effects and `_status_*` macros | `led_effect` |
| `stealthburner_leds.cfg` | Stealthburner logo status (`_STATUS STATE=...`: heating and print progress as a filling logo, paused, error flash from `_ERROR`, part ready once the bed is cool, dim when idle and nobody is near) and the nozzle light | `led_effect`, `neopixel:bt_logo` and `rainbow_turtle` from AFC |
| **sensors/** | | |
| `motion_sensor.cfg` | PIR motion sensor switching the case light | sensor on a pin, `[output_pin caselight]` |
| `motion_sensor.cfg` | PIR motion sensor: case light and nozzle LEDs on while someone is near (timeout from the last motion), `CASELIGHT MODE=AUTO\|ON\|OFF` | sensor on a pin, `[output_pin caselight]`, `leds/stealthburner_leds.cfg` |
### Klipper modules (`extras/`)
+2
View File
@@ -544,6 +544,7 @@ gcode:
{% set pos = printer.gcode_move.gcode_position %}
SAVE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state
_STATUS_SHOW STATE=cleaning
G90
@@ -576,6 +577,7 @@ gcode:
{% endif %}
RESTORE_GCODE_STATE NAME=BLOBIFIER_CLEAN_state
_STATUS
+166 -248
View File
@@ -1,216 +1,191 @@
# Stealthburner LEDs: logo status effects (_STATUS) and the nozzle light
#
# Based on the Rainbow Barf logo LED effects by tanaes:
# https://github.com/tanaes/whopping_Voron_mods/blob/main/LEDs/Rainbow_Barf_Logo_LED/Code/stealthburner_led_effects_barf.cfg
# Macros for setting the status leds on the Voron StealthBurner toolhead (or for any neopixel-type leds).
# which builds on the Voron Stealthburner LED macros. Needs klipper-led_effect.
#
# You will need to configure a neopixel (or other addressable led, such as dotstar). See
# https://www.klipper3d.org/Config_Reference.html#neopixel for configuration details.
#####################################
# INSTRUCTIONS #
#####################################
# How to use all this stuff:
# sb_leds 1-8 are the logo, 9-10 the nozzle LEDs. The logo shows the printer
# status (_STATUS); the nozzle LEDs are white while someone is near the
# printer (sensors/motion_sensor.cfg). led_effect adds up effects that share
# an LED, so the logo effects only cover 1-8 and never stop the nozzle light.
#
# 1. Copy this .cfg file into your Klipper config directory and then add [include stealthburner_leds.cfg]
# to the top of your printer.cfg in order for register the LEDs and macros with Klipper.
# 2. Define your LEDs by editing [neopixel sb_leds] below and entering the data pin from your control board
# as well as the color order.
# _STATUS STATE=<state> set and show a status
# _STATUS show the current status again
# _STATUS_SHOW STATE=... show a status without storing it (cleaning)
# _STATUS_FLASH STATE=... show a status for a while (_ERROR: error)
#
# Note: RGB and RGBW are different and must be defined explicitly. RGB and RGBW are also not able to
# be mix-and-matched in the same chain. A separate data line would be needed for proper functioning.
#
# RGBW LEDs will have a visible yellow-ish phosphor section to the chip. If your LEDs do not have
# this yellow portion, you have RGB LEDs.
#
# 3. Save your config and restart Klipper.
#
# Note: We set RED and BLUE to 1.0 to make it easier for users and supporters to detect
# misconfigurations or miswiring. The default color format is for Neopixels with a dedicated
# white LED. On startup, all three SB LEDs should light up.
#
# If you get random colors across your LEDs, change the color_order to GRB and restart. Then
# omit the W for each suggested color_order in the next paragraph.
#
# If you get MAGENTA, your color order is correct. If you get CYAN, you need to use RGBW. If
# you get YELLOW, you need to use BRGW (note that BRG is only supported in the latest Klipper
# version).
#
# 4. Once you have confirmed that the LEDs are set up correctly, you must now decide where you want
# these macros called up...which means adding them to your existing gcode macros. NOTHING will happen
# unless you add the STATUS_????? macros to your existing gcode macros.
#
# Example: add STATUS_LEVELING to the beginning of your QGL gcode macro, and then add STATUS_READY
# to the end of it to set the logo LED and nozzle LEDs back to the `ready` state.
#
# Example: add STATUS_CLEANING to the beginning of your nozzle-cleaning macro, and then STATUS_READY
# to the end of it to return the LEDs back to `ready` state.
#
# 5. Feel free to change colors of each macro, create new ones if you have a need to. The macros provided below
# are just an example of what is possible. If you want to try some more complex animations, you will most
# likely have to use WLED with Moonraker and a small micro-controller (please see the LED thread for help inside
# of the stealthburner_beta channel on Discord).
#
#####################################
# END INSTRUCTRUCTIONS #
#####################################
# States: ready, homing, heating_bed, heating_extruder, calibrating_z,
# leveling, meshing, cleaning, printing, paused, part_ready, error.
# ready: rainbow while someone is near, dim (logo and Box Turtle
# logo) when nobody is near
# heating_*: the logo fills up with the temperature towards the target
# printing: the logo fills up with the print progress
# part_ready: blue while the bed is above part_ready_temp, then green
[neopixel sb_leds]
pin: nhk:PD3
# The pin connected to the neopixel. This parameter must be provided.
chain_count: 10
# The number of Neopixel chips that are "daisy chained" to the
# provided pin. The default is 1 (which indicates only a single
# Neopixel is connected to the pin).
# color_order: GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRBW, GRBW
color_order: GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB
# Set the pixel order required by the LED hardware. Options are GRB,
# RGB, GRBW, or RGBW. The default is GRB.
color_order: GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB, GRB
# Magenta until the first effect starts: shows that the chain and the
# colour order are right
initial_RED: 1.0
initial_GREEN: 0.0
initial_BLUE: 1.0
initial_WHITE: 0.0
# Sets the initial LED color of the Neopixel. Each value should be
# between 0.0 and 1.0. The WHITE option is only available on RGBW
# LEDs. The default for each color is 0.#
##########################
# LED Effects Animations #
##########################
# led_effect sends the whole chain at the rate of the fastest effect running
# on it, so all sb_leds effects use 12 fps.
##################
## logo effects ##
##################
[led_effect sb_logo_busy]
[led_effect sb_logo_ready]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (1,0,0)
gradient 0.3 1 add (0.3, 0.0, 0.0),(0.0, 0.3, 0.0),(0.0, 0.0, 0.3)
[led_effect sb_logo_cleaning]
[led_effect sb_logo_night]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 0.02, 0.5)
static 0 0 top (0.02, 0.02, 0.02)
[led_effect sb_logo_calibrating_z]
[led_effect bt_logo_night]
autostart: false
frame_rate: 24
frame_rate: 10
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
neopixel:bt_logo
layers:
breathing 3 1 top (0.0, 0.0, 0.35)
[led_effect sb_logo_heating]
leds:
neopixel:sb_leds (2,3,7,8,6,1)
autostart: false
frame_rate: 24
layers:
comet 0.3 0 add (1, 0.18, 0)
[led_effect sb_logo_cooling]
leds:
neopixel:sb_leds (2,3,7,8,6,1)
autostart: false
frame_rate: 24
layers:
comet 0.3 0 add (0, 0, 1)
static 0 0 top (0.02, 0.02, 0.02)
[led_effect sb_logo_homing]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 0.6, 0.2)
breathing 3 1 top (0.0, 0.6, 0.2)
# heatergauge: the LEDs light up one by one with temperature / target
[led_effect sb_logo_heating_bed]
autostart: false
frame_rate: 12
heater: heater_bed
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
heatergauge -1 0 add (1.0, 0.18, 0.0),(1.0, 0.18, 0.0)
static 0 0 top (0.08, 0.015, 0.0)
[led_effect sb_logo_heating_extruder]
autostart: false
frame_rate: 12
heater: extruder
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
heatergauge -1 0 add (1.0, 0.0, 0.0),(1.0, 0.0, 0.0)
static 0 0 top (0.08, 0.0, 0.0)
[led_effect sb_logo_calibrating_z]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 0.0, 0.35)
[led_effect sb_logo_leveling]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.5, 0.1, 0.4)
breathing 3 1 top (0.5, 0.1, 0.4)
[led_effect sb_logo_meshing]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.2, 1.0, 0.0)
breathing 3 1 top (0.2, 1.0, 0.0)
[led_effect sb_logo_cleaning]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 0.02, 0.5)
# progress: the LEDs light up one by one with the print progress
# (display_status: M73 from the slicer, else the file position)
[led_effect sb_logo_printing]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
gradient 0.3 1 add (0.3, 0.0, 0.0),(0.3, 0.3, 0.0),(0.3, 0.1, 0.0)
progress -1 0 add (0.3, 0.3, 0.3),(0.3, 0.3, 0.3)
static 0 0 top (0.08, 0.02, 0.0)
[led_effect sb_logo_standby]
[led_effect sb_logo_paused]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.01, 0.01, 0.01)
breathing 2 1 top (1.0, 0.35, 0.0)
[led_effect sb_logo_cooling]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 0.0, 1.0)
[led_effect sb_logo_part_ready]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 1.0, 0.0)
breathing 3 1 top (0.0, 1.0, 0.0)
####################
## nozzle effects ##
####################
[led_effect sb_nozzle_heating]
[led_effect sb_logo_error]
autostart: false
frame_rate: 24
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
blink 1 0.5 top (1.0, 0.0, 0.0)
###################
## nozzle effect ##
###################
# Switched by _LIGHTS (sensors/motion_sensor.cfg)
[led_effect sb_nozzle_light]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (9,10)
layers:
breathing 3 1 top (1.0, 0.18, 0.0, 0.0)
[led_effect sb_nozzle_cooling]
autostart: false
frame_rate: 24
leds:
neopixel:sb_leds (9,10)
layers:
breathing 3 1 top (0.0, 0.0, 1.0, 0.1)
[led_effect sb_nozzle_standby]
autostart: false
frame_rate: 24
leds:
neopixel:sb_leds (9,10)
layers:
breathing 3 1 top (0.6, 0.0, 0.0, 0.0)
[led_effect sb_nozzle_part_ready]
autostart: false
frame_rate: 24
leds:
neopixel:sb_leds (9,10)
layers:
breathing 3 1 top (0.6, 1.0, 0.0, 0.1)
static 0 0 top (1.0, 1.0, 1.0)
#####################
## all led effects ##
#####################
# Klipper shutdown
[led_effect sb_critical_error]
leds:
neopixel:sb_leds
@@ -222,129 +197,72 @@ autostart: false
frame_rate: 24
run_on_error: true
[led_effect rainbow]
leds:
neopixel:sb_leds
autostart: true
frame_rate: 24
layers:
gradient 0.3 1 add (0.3, 0.0, 0.0),(0.0, 0.3, 0.0),(0.0, 0.0, 0.3)
#######################
# LED Effects Statics #
#######################
[led_effect set_nozzle_leds]
leds:
neopixel:sb_leds (9,10)
#neopixel:caselight
autostart: false
frame_rate: 24
layers:
# static 0 0 top (0.0, 0.0, 0.0, 1.0)
static 0 0 top (1.0, 1.0, 1.0, 1.0)
[led_effect set_logo_leds]
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
#neopixel:caselight
autostart: false
frame_rate: 24
layers:
static 0 0 top (1.0, 1.0, 1.0)
##############
# The Macros #
##############
[gcode_macro _set_logo_leds_off]
[gcode_macro _STATUS]
description: Set the logo status (STATE=ready, homing, heating_bed, ...); without STATE show the current one again
variable_state: 'ready'
variable_part_ready_temp: 35 # part_ready: blue until the bed is below this (C), then green
variable_fade_time: 0.5 # s cross-fade between effects (logo and nozzle light)
gcode:
SET_LED_EFFECT EFFECT=set_logo_leds STOP=1
{% set new = params.STATE|default(state)|lower %}
{% if new != state %}
SET_GCODE_VARIABLE MACRO=_STATUS VARIABLE=state VALUE="'{new}'"
{% endif %}
_STATUS_SHOW STATE={new}
[gcode_macro _set_logo_leds_on]
[gcode_macro _STATUS_SHOW]
description: Show STATE on the logo without storing it as the current status
gcode:
SET_LED_EFFECT EFFECT=set_logo_leds
{% set state = params.STATE|lower %}
{% set cfg = printer['gcode_macro _STATUS'] %}
{% set near = printer['gcode_macro _LIGHTS'].near if 'gcode_macro _LIGHTS' in printer else True %}
{% set night = state == 'ready' and not near %}
{% set cool = printer.heater_bed.temperature < cfg.part_ready_temp %}
{% if state == 'ready' %}
{% set effect = 'sb_logo_night' if night else 'sb_logo_ready' %}
{% elif state == 'part_ready' %}
{% set effect = 'sb_logo_part_ready' if cool else 'sb_logo_cooling' %}
{% else %}
{% set effect = 'sb_logo_' ~ state %}
{% endif %}
{% if ('led_effect ' ~ effect) in printer %}
# REPLACE: stops the other effects on the logo LEDs, not the nozzle light
SET_LED_EFFECT EFFECT={effect} REPLACE=1 FADETIME={cfg.fade_time}
SET_LED_EFFECT EFFECT={'bt_logo_night' if night else 'rainbow_turtle'} REPLACE=1 FADETIME={cfg.fade_time}
{% else %}
_WARN MSG="_STATUS: unknown state {state}"
{% endif %}
{% if state == 'part_ready' and not cool %}
UPDATE_DELAYED_GCODE ID=_status_part_ready_check DURATION=30
{% endif %}
[gcode_macro _set_nozzle_leds_on]
[delayed_gcode _status_part_ready_check]
gcode:
SET_LED_EFFECT EFFECT=set_nozzle_leds
{% if printer['gcode_macro _STATUS'].state == 'part_ready' %}
_STATUS
{% endif %}
[gcode_macro _set_nozzle_leds_off]
[gcode_macro _STATUS_FLASH]
description: Show STATE on the logo for DURATION seconds (default 10), then the current status again
gcode:
SET_LED_EFFECT EFFECT=set_nozzle_leds STOP=1
_STATUS_SHOW STATE={params.STATE}
UPDATE_DELAYED_GCODE ID=_status_flash_end DURATION={params.DURATION|default(10)|float}
# The _status_* macros only stop the toolhead effects (neopixel:sb_leds), so
# the Box Turtle logo (rainbow_turtle on neopixel:bt_logo) keeps running during
# prints. _status_off still stops everything; _status_ready starts the logo again.
[gcode_macro _status_off]
# After an error that ended the print (print_stats: error) the logo stays red
# until the next status (next print, CANCEL_PRINT, idle timeout)
[delayed_gcode _status_flash_end]
gcode:
STOP_LED_EFFECTS
{% set state = printer['gcode_macro _STATUS'].state %}
{% if printer.print_stats.state == 'error' and state not in ['ready', 'part_ready'] %}
_STATUS STATE=error
{% else %}
_STATUS
{% endif %}
[gcode_macro _status_ready]
[delayed_gcode _status_startup]
initial_duration: 1
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=rainbow
SET_LED_EFFECT EFFECT=rainbow_turtle
[gcode_macro _status_part_ready]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_nozzle_part_ready
SET_LED_EFFECT EFFECT=sb_logo_part_ready
[gcode_macro _status_busy]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_busy
_set_nozzle_leds_on
[gcode_macro _status_heating]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_heating
SET_LED_EFFECT EFFECT=sb_nozzle_heating
[gcode_macro _status_cooling]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_cooling
SET_LED_EFFECT EFFECT=sb_nozzle_cooling
[gcode_macro _status_leveling]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_leveling
_set_nozzle_leds_on
[gcode_macro _status_homing]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_homing
_set_nozzle_leds_on
[gcode_macro _status_cleaning]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_cleaning
_set_nozzle_leds_on
[gcode_macro _status_meshing]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_meshing
_set_nozzle_leds_on
[gcode_macro _status_calibrating_z]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_calibrating_z
_set_nozzle_leds_on
[gcode_macro _status_printing]
gcode:
STOP_LED_EFFECTS LEDS="neopixel:sb_leds"
SET_LED_EFFECT EFFECT=sb_logo_printing
_set_nozzle_leds_on
_STATUS STATE=ready
+3
View File
@@ -18,6 +18,9 @@
description: Show DISPLAY (default MSG) on the display, then raise MSG as an error (aborts the calling macros)
gcode:
M117 {params.DISPLAY|default(params.MSG)}
{% if 'gcode_macro _STATUS_FLASH' in printer %}
_STATUS_FLASH STATE=error
{% endif %}
_RAISE_ERROR MSG="{params.MSG}"
[gcode_macro _RAISE_ERROR]
+20 -4
View File
@@ -422,11 +422,14 @@ gcode:
{% else %}
CHANGE_TOOL LANE={lane}
# Nozzle temp: use the extruder's current target, which AFC
# already sets from Spoolman when the lane was loaded. Fall
# back to the configured default if nothing is set yet.
# Nozzle temp: the lane's own filament temperature (AFC, from
# Spoolman). Not printer.extruder.target: the template is rendered
# before CHANGE_TOOL runs, so that is still the previous lane's
# (or the print's) temperature. PA_CALIBRATE heats to it (M109).
{% set lane_obj = printer["AFC_stepper " ~ lane] if ("AFC_stepper " ~ lane) in printer else {} %}
{% set lane_temp = lane_obj.extruder_temp|default(0, true)|float %}
{% set target = printer.extruder.target|default(0)|float %}
{% set nozzle_temp = target if target > 0 else cfg.fallback_nozzle_temp|float %}
{% set nozzle_temp = lane_temp if lane_temp > 0 else (target if target > 0 else cfg.fallback_nozzle_temp|float) %}
{action_respond_info("Calibrating PA for %s (spool %d) at %.0fC..." % (lane, spool_id, nozzle_temp))}
M117 Calibrating PA: {lane}
@@ -619,6 +622,19 @@ gcode:
UPDATE_DELAYED_GCODE ID=_PA_POLL_LANE_CHANGE DURATION=2
# PA_CALIBRATE_ALL_LANES sets the PA of every lane in turn (the last one
# wins), and the lane-change poll only reacts to a change of the loaded lane.
# Run this after it so the PA matches the lane that is actually loaded.
[gcode_macro _PA_APPLY_LOADED_LANE]
description: Apply the cached PA of the lane loaded in the toolhead
gcode:
{% set lane = printer.AFC.current_load|default(none) if "AFC" in printer else none %}
{% if lane %}
_PA_APPLY_FOR_LANE LANE={lane}
{% else %}
RESPOND MSG="_PA_APPLY_LOADED_LANE: no lane loaded, PA unchanged"
{% endif %}
[gcode_macro _PA_APPLY_FOR_LANE]
description: Internal -- applies cached PA for a lane without calibrating
# LANE=<lane_name>
+1 -1
View File
@@ -16,7 +16,7 @@ gcode:
{% if printer.pause_resume.is_paused|lower == 'false' and park|lower == 'true'%}
_TOOLHEAD_PARK_PAUSE_CANCEL
{% endif %}
_status_ready
_STATUS STATE=ready
# A list of G-Code commands to execute on an idle timeout. See
# docs/Command_Templates.md for G-Code format. The default is to run
# "TURN_OFF_HEATERS" and "M84".
+4 -2
View File
@@ -41,6 +41,7 @@ gcode:
PAUSE_BASE
_TOOLHEAD_PARK_PAUSE_CANCEL
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=True
_STATUS STATE=paused
# Set fan to S28 (28/255 ≈ 0.1098)
M106 S28
{% else %}
@@ -96,7 +97,7 @@ gcode:
{% endif %}
RESUME_BASE {get_params}
_status_printing
_STATUS STATE=printing
# Raising an error (_ERROR, also shown on the display) aborts the whole
# RESUME like a failed purge check: the printer stays paused and the next
@@ -203,7 +204,8 @@ gcode:
SET_GCODE_VARIABLE MACRO=PAUSE VARIABLE=parked VALUE=False
# Clear a pause reason from the display
M117
_status_ready
_STATUS STATE=ready
_LIGHTS_ON
[gcode_macro M600]
#
+73 -125
View File
@@ -1,59 +1,39 @@
# Print start and end: PRINT_WARMUP, PRINT_START, PRINT_END
# Idle time (in seconds) to wait before running the above G-Code
# commands. The default is 600 seconds.
#####################################################################
# Macros
#####################################################################
# [gcode_macro PRINT_START]
# gcode:
# PRINT_WARMUP BED={params.BED} EXTRUDER={params.EXTRUDER} CHAMBER={params.CHAMBER|default("0")} TOOL={params.TOOL|default("0")}
# PRINT_START_2 EXTRUDER={params.EXTRUDER}
# OrcaSlicer calls PRINT_WARMUP and then PRINT_START. HEAT_SOAK at the end of
# PRINT_WARMUP pauses the print file and resumes it when the soak is done, so
# PRINT_START runs on a soaked bed:
# PRINT_WARMUP bed heats while the nozzle cools and the printer homes,
# wait for the bed, HEAT_SOAK
# PRINT_START QGL, contact Z calibration, mesh, load the initial tool,
# PA for all lanes, XY reference
# The filament is loaded after the Z calibration, so the contact always
# touches a clean nozzle that has not been oozing at 150C for minutes.
[gcode_macro PRINT_WARMUP]
description: Perform initial homing and heating tasks
description: Print start before HEAT_SOAK: home while the bed heats, wait for the bed, soak
gcode:
{% set target_bed = params.BED|int %}
{% set target_extruder = params.EXTRUDER|int %}
{% set target_chamber = params.CHAMBER|default("0")|int %}
# {% set x_wait = printer.toolhead.axis_maximum.x|float / 2 %}
# {% set y_wait = printer.toolhead.axis_maximum.y|float / 2 %}
{% set initial_tool = params.TOOL|default("0")|int %}
{% set chamber_temp = printer["temperature_sensor chamber"].temperature|float %}
RESET_FAILURE
CLEAR_PAUSE
CLEAR_PAUSE
# Clear what an earlier print or error left on the display
M117
_motion_detected
_LIGHTS_ON
#SET_PIN PIN=caselight VALUE=1.00
UPDATE_DELAYED_GCODE ID=_delayed_motors_off DURATION=0
BED_MESH_CLEAR
SET_GCODE_OFFSET Z=0
CLEAR_PAUSE
SKEW_PROFILE LOAD=Califlower
M106 S0
{% set current_temp = printer.extruder.temperature %}
{% if current_temp > 150 %}
RESPOND MSG="nozzle to hot, lowering to 150"
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
{% endif %}
_status_homing
RESPOND MSG="homing"
HOME
RESPOND MSG="homing finished"
# G0 Z2 ; position beacon at 2mm for heat soak
# Bed first, so it heats during the rest of the warmup
{% if target_bed < 60 %}
RESPOND MSG="Using PID for <60°C bed"
SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} PID_KP=33.606 PID_KI=0.694 PID_KD=407.058
@@ -62,48 +42,43 @@ gcode:
SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET={target_bed} pid_Kp=46.843 pid_Ki=2.002 pid_Kd=274.034
{% endif %}
G1 X175 Y175 Z2 F1200
_status_heating
RESPOND MSG="heating"
# Only to get the toolhead over the bed for the soak; the Z that counts
# is the contact calibration in PRINT_START on the soaked bed
_STATUS STATE=homing
_NOZZLE_CONTACT_TEMP
RESPOND MSG="homing"
HOME
G1 X175 Y175 Z5 F1200
_STATUS STATE=heating_bed
{% if target_bed > 0 %}
M140 S{target_bed} ; start bed heater
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
M190 S{target_bed} ; wait on bed temperature
RESPOND MSG="heating"
M190 S{target_bed}
{% endif %}
HOME
QUAD_GANTRY_LEVEL
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
G1 X175 Y175 Z5 F1200
_HEAT_FOR_LOADED_LANE TOOL={initial_tool} ; unload needs the loaded filament's temperature
T{initial_tool} #PURGE_LENGTH=100 #Load Initial Tool
M104 S{target_extruder} ; set extruder to print temp
M109 S{target_extruder} ; wait for extruder temp
_NOZZLE_RETRACT LENGTH=2 ; no oozing while waiting; PRINT_START pushes it back
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
G1 X175 Y175 Z5 F1200
{% if target_chamber > 30 %}
RESPOND MSG="waiting for chamber temperature"
M141 S{target_chamber}
# M191 S{target_chamber} ; Waits until the chamber temperature reaches 60°C
# TEMPERATURE_WAIT SENSOR="temperature_sensor chamber" MINIMUM={target_chamber}
M106 S255
# HEAT_SOAK HEATER='heater_bed' TARGET={BED_TEMP} SOAKER='temperature_sensor iHeater_S' SOAK_TEMP={target_chamber} TIMEOUT=60 CANCEL='_NOTHING'
# Unreachable SOAK_TEMP + CANCEL='_NOTHING': soaks until the TIMEOUT, then continues the print
HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor chamber' SOAK_TEMP={target_chamber} TIMEOUT=60 CANCEL='_NOTHING'
# (CANCEL='_NOTHING') and having unreachable SOAK_TEMP makes it run till the TIMEOUT and continue without canceling the print.
{% else %}
RESPOND MSG="waiting for bed core temperature"
HEAT_SOAK HEATER='heater_bed' TARGET={target_bed} SOAKER='temperature_sensor bed_core' SOAK_TEMP={target_bed - 5} TIMEOUT=30 CANCEL='_NOTHING'
# (CANCEL='_NOTHING') and having unreachable SOAK_TEMP makes it run till the TIMEOUT and continue without canceling the print.
{% endif %}
# Beacon contact refuses a nozzle above contact_max_hotend_temperature (180C)
[gcode_macro _NOZZLE_CONTACT_TEMP]
description: Nozzle to 150C for Beacon contact; wait only while it is above MAXIMUM (default 170C), WAIT=1 also waits until it is at least 145C
gcode:
{% set max = params.MAXIMUM|default(170)|float %}
{% set heat = params.WAIT|default(0)|int == 1 %}
M104 S150
{% if heat %}
TEMPERATURE_WAIT SENSOR=extruder MINIMUM=145 MAXIMUM={max}
{% elif printer.extruder.temperature > max %}
RESPOND MSG="Nozzle at {printer.extruder.temperature|round|int}C, waiting until it is below {max|int}C"
TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={max}
{% endif %}
# AFC heats for a tool change from the print file's per-tool temperatures.
@@ -130,86 +105,59 @@ gcode:
RESUME_BASE
[gcode_macro PRINT_START]
description: Print start after HEAT_SOAK: QGL, Z calibration, mesh, load the initial tool, PA
gcode:
RESPOND MSG="print start macro continued"
_motion_detected
{% set target_extruder = params.EXTRUDER|int %}
{% set initial_tool = params.TOOL|default("0")|int %}
RESPOND MSG="print start macro continued"
_LIGHTS_ON
M106 S0
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
HOME
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
_status_calibrating_z
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_status_leveling
RESPOND MSG="quad ganrty level"
# The bed is soaked now: level and calibrate Z on the final geometry
_STATUS STATE=leveling
RESPOND MSG="quad gantry level"
QUAD_GANTRY_LEVEL
_status_meshing
BLOBIFIER_CLEAN
_STATUS STATE=calibrating_z
_NOZZLE_CONTACT_TEMP WAIT=1
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_STATUS STATE=meshing
RESPOND MSG="meshing"
BED_MESH_CALIBRATE RUNS=2 ; bed mesh in scan mode
BLOBIFIER_CLEAN ; call another macro to wipe nozzle if available
# Heat over the bucket, then undo the retracts of the previous PRINT_END
_STATUS STATE=heating_extruder
BLOBIFIER_PARK
M109 S{target_extruder}
_NOZZLE_UNRETRACT
M104 S150 ; set nozzle temp to 150
M109 S150 ; wait until nozzle reaches 150 ; wait until nozzle reaches 0
_status_calibrating_z
G28 Z METHOD=CONTACT CALIBRATE=1 ; calibrate z offset and beacon model hot
_status_heating
M104 S{target_extruder} ; set extruder to print temp
M109 S{target_extruder} ; wait for extruder temp
BLOBIFIER_PARK ; over the bucket, then undo the retracts
_NOZZLE_UNRETRACT ; of PRINT_WARMUP and the previous PRINT_END
# ; needs fine tuning, long meltzones require more
# SET_GCODE_OFFSET Z_ADJUST={OFFSET} ; apply optional material squish via slicer
#SET_GCODE_OFFSET Z=-0.06 ; squish
# SET_GCODE_OFFSET Z=0.02 ; squish # worked before but a bit to high now
# SET_GCODE_OFFSET Z=-0.05 ; squish
SET_GCODE_OFFSET Z=-0.00 ; squish
RESPOND MSG="starting"
;PRIME_NOZZLE ; call another macro to purge or prime nozzle
# WIPE_NOZZLE ; call another macro to wipe nozzle if available
# Line_Purge
# AFC_POOP PURGE_LENGTH=100
# AFC_KICK
BLOBIFIER_CLEAN
# Load the initial tool (unloading another lane needs that lane's temperature)
_HEAT_FOR_LOADED_LANE TOOL={initial_tool}
T{initial_tool}
PA_CALIBRATE_ALL_LANES LANES="lane1,lane2,lane3,lane4,lane5"
# A calibration can leave another lane loaded, and every cached lane
# sets its PA: load the initial tool again and apply its PA
T{initial_tool}
_PA_APPLY_LOADED_LANE
M104 S{target_extruder} ; set extruder to print temp
M109 S{target_extruder} ; wait for extruder temp
M109 S{target_extruder}
SET_GCODE_OFFSET Z=-0.00 ; squish
BLOBIFIER_CLEAN
; start printing
G90 ; absolute positioning
G1 Z20 F30000 ; move nozzle away from bed
G1 X175 Y175 F30000 ; move nozzle away from bed
G28 XYZ
#G11 ; unretract
# XY reference for AFC_XY_SAFETY_CHECK (homes X and Y; Z stays from the
# contact calibration)
_AFC_STORE_HOME_REFERENCE
# bdwidth is not used while printing: its motion reading stays at 0 and its
# per-reading width compensation made the flow jump between 77 and 119%.
# To use it again: SET_BDWIDTH NAME=fila_width_0 COMMAND=ENABLE_WIDTH
_status_printing
RESPOND MSG="starting"
_STATUS STATE=printing
[gcode_macro PRINT_END]
@@ -223,7 +171,7 @@ gcode:
SAVE_GCODE_STATE NAME=STATE_PRINT_END
_motion_detected
_LIGHTS_ON
M400 ; wait for buffer to clear
G92 E0 ; zero the extruder
@@ -238,7 +186,7 @@ gcode:
M107 ; turn off fan
#SET_PIN PIN=caselight VALUE=0.03
_status_part_ready
_STATUS STATE=part_ready
UPDATE_DELAYED_GCODE ID=_delayed_motors_off DURATION=3600
+91 -25
View File
@@ -1,42 +1,108 @@
# PIR motion sensor: case light on when someone is near the printer
# PIR motion sensor (AM312): case light and nozzle LEDs while someone is near
#
# The AM312 keeps its output on as long as it sees movement: press = motion,
# release = no more motion. The timeout starts at the release, so the lights
# stay on while someone works at the printer.
#
# someone near: case light near_value, nozzle LEDs white
# nobody near, print/pause: case light print_value, nozzle LEDs off
# nobody near, idle: case light idle_value, nozzle LEDs off,
# logo and Box Turtle logo dim (_STATUS ready)
#
# CASELIGHT MODE=ON [VALUE=0.5] | OFF | AUTO overrides the sensor until the
# next Klipper restart. Setting the case light in Mainsail only lasts until
# the next motion.
[gcode_button am312]
pin: !PC0
press_gcode:
_motion_detected
_MOTION_START
release_gcode:
_MOTION_END
[gcode_macro _motion_detected]
description: Motion sensor triggered
[gcode_macro _LIGHTS]
description: Set the case light and nozzle LEDs from motion, print state and CASELIGHT mode
variable_timeout: 60 # s without motion before the lights dim or turn off
variable_near_value: 1.0 # case light while someone is near
variable_print_value: 0.1 # case light while printing or paused, nobody near
variable_idle_value: 0.0 # case light while idle, nobody near
variable_on_value: 1.0 # case light for CASELIGHT MODE=ON
variable_mode: 'auto' # auto (motion sensor), on, off: set by CASELIGHT
variable_present: False # someone near: set by the motion sensor
variable_near: False # lights on (present or MODE=ON): read by _STATUS
variable_debug: False # True: report every change in the console
gcode:
{% set printing = printer.print_stats.state == "printing" %}
# RESPOND MSG="AM312: Motion detected"
{% if printing %}
# RESPOND MSG="AM312: Printer is printing -> light ON (100%)"
SET_PIN PIN=caselight VALUE=1.0
_set_nozzle_leds_on
{% set busy = printer.print_stats.state in ['printing', 'paused'] %}
{% if mode == 'on' %}
{% set lit = True %}
{% set value = on_value %}
{% elif mode == 'off' %}
{% set lit = False %}
{% set value = 0.0 %}
{% else %}
# RESPOND MSG="AM312: Printer idle -> light ON (10%)"
SET_PIN PIN=caselight VALUE=0.1
_set_nozzle_leds_off
{% set lit = present %}
{% set value = near_value if present else (print_value if busy else idle_value) %}
{% endif %}
{% if debug %}
RESPOND MSG="Lights: mode={mode} present={present} print={printer.print_stats.state}: case light {value}, nozzle {'on' if lit else 'off'}"
{% endif %}
{% if printer['output_pin caselight'].value != value %}
SET_PIN PIN=caselight VALUE={value}
{% endif %}
{% if printer['led_effect sb_nozzle_light'].enabled != lit %}
SET_LED_EFFECT EFFECT=sb_nozzle_light {'' if lit else 'STOP=1'} FADETIME={printer['gcode_macro _STATUS'].fade_time}
{% endif %}
{% if near != lit %}
SET_GCODE_VARIABLE MACRO=_LIGHTS VARIABLE=near VALUE={lit}
# Night mode of the logo when idle
_STATUS
{% endif %}
# RESPOND MSG="AM312: Resetting timeout to 30 seconds"
UPDATE_DELAYED_GCODE ID=_motion_timeout DURATION=30
[gcode_macro _MOTION_START]
description: Motion sensor: someone is near
gcode:
UPDATE_DELAYED_GCODE ID=_motion_timeout DURATION=0
{% if not printer['gcode_macro _LIGHTS'].present %}
SET_GCODE_VARIABLE MACRO=_LIGHTS VARIABLE=present VALUE=True
_LIGHTS
{% endif %}
[gcode_macro _MOTION_END]
description: Motion sensor: no more motion, lights off after the timeout
gcode:
UPDATE_DELAYED_GCODE ID=_motion_timeout DURATION={printer['gcode_macro _LIGHTS'].timeout}
[delayed_gcode _motion_timeout]
gcode:
{% set printing = printer.print_stats.state == "printing" %}
SET_GCODE_VARIABLE MACRO=_LIGHTS VARIABLE=present VALUE=False
_LIGHTS
# RESPOND MSG="AM312: Timeout reached, no motion"
[gcode_macro _LIGHTS_ON]
description: Lights on as if someone walked by (print start and end, startup)
gcode:
_MOTION_START
{% if printer['gcode_button am312'].state == 'RELEASED' %}
_MOTION_END
{% endif %}
{% if printing %}
# RESPOND MSG="AM312: Printing -> dim light to 10%"
SET_PIN PIN=caselight VALUE=0.1
[delayed_gcode _lights_startup]
initial_duration: 2
gcode:
_LIGHTS_ON
[gcode_macro CASELIGHT]
description: Case light and nozzle LEDs: MODE=AUTO (motion sensor), ON [VALUE=0-1] or OFF; no MODE: show the mode
gcode:
{% set l = printer['gcode_macro _LIGHTS'] %}
{% set mode = params.MODE|default('')|lower %}
{% if mode == '' %}
RESPOND MSG="Case light: mode {l.mode}, {'someone near' if l.present else 'nobody near'}, value {printer['output_pin caselight'].value}"
{% elif mode not in ['auto', 'on', 'off'] %}
_ERROR MSG="CASELIGHT: MODE must be AUTO, ON or OFF"
{% else %}
# RESPOND MSG="AM312: Idle -> light OFF"
SET_PIN PIN=caselight VALUE=0.0
{% if 'VALUE' in params %}
SET_GCODE_VARIABLE MACRO=_LIGHTS VARIABLE=on_value VALUE={[[params.VALUE|float, 0.0]|max, 1.0]|min}
{% endif %}
SET_GCODE_VARIABLE MACRO=_LIGHTS VARIABLE=mode VALUE="'{mode}'"
_LIGHTS
{% endif %}
_set_nozzle_leds_off