Files
klipper-macros/macros/leds/stealthburner_leds.cfg
T
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

269 lines
8.2 KiB
INI

# 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
# which builds on the Voron Stealthburner LED macros. Needs klipper-led_effect.
#
# 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.
#
# _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)
#
# 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
chain_count: 10
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
# 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_ready]
autostart: false
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.0, 0.3, 0.0),(0.0, 0.0, 0.3)
[led_effect sb_logo_night]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
static 0 0 top (0.02, 0.02, 0.02)
[led_effect bt_logo_night]
autostart: false
frame_rate: 10
leds:
neopixel:bt_logo
layers:
static 0 0 top (0.02, 0.02, 0.02)
[led_effect sb_logo_homing]
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.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: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.5, 0.1, 0.4)
[led_effect sb_logo_meshing]
autostart: false
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)
[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: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
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_paused]
autostart: false
frame_rate: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
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: 12
leds:
neopixel:sb_leds (2,1,3,4,5,6,7,8)
layers:
breathing 3 1 top (0.0, 1.0, 0.0)
[led_effect sb_logo_error]
autostart: false
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:
static 0 0 top (1.0, 1.0, 1.0)
#####################
## all led effects ##
#####################
# Klipper shutdown
[led_effect sb_critical_error]
leds:
neopixel:sb_leds
layers:
strobe 1 1.5 add (1.0, 1.0, 1.0)
breathing 2 0 difference (0.95, 0.0, 0.0)
static 1 0 top (1.0, 0.0, 0.0)
autostart: false
frame_rate: 24
run_on_error: true
##############
# The Macros #
##############
[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 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 _STATUS_SHOW]
description: Show STATE on the logo without storing it as the current status
gcode:
{% 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 %}
[delayed_gcode _status_part_ready_check]
gcode:
{% if printer['gcode_macro _STATUS'].state == 'part_ready' %}
_STATUS
{% endif %}
[gcode_macro _STATUS_FLASH]
description: Show STATE on the logo for DURATION seconds (default 10), then the current status again
gcode:
_STATUS_SHOW STATE={params.STATE}
UPDATE_DELAYED_GCODE ID=_status_flash_end DURATION={params.DURATION|default(10)|float}
# 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:
{% 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 %}
[delayed_gcode _status_startup]
initial_duration: 1
gcode:
_STATUS STATE=ready