Frix-x / klippain

Generic Klipper configuration for 3D printers
GNU General Public License v3.0
837 stars 220 forks source link

WLED/Led_effect implementation #142

Closed s0ybean closed 6 months ago

s0ybean commented 1 year ago

Hi,

Just wondering if you have any ideas how an end user could implement WLED? All of the current lighting calls are baked into the non-modifiable macros and use a specific format. That makes it a bit hard to use overrides (from what I understand) since we wouldn't really need to specify rgb values or use the current format.

WLED allows us to use complex animations and offload the processing to a very inexpensive esp32. All of the setup is done on the esp32 gui.

To use it in klipper, we simply add WLED to moonraker via IP or serial, and call the specific preset that we want (which was created through the WLED interface on the esp32).

For example:

WLED_ON string=chamber preset=1

This would load any complex animations or effects we set up for preset 1 without any extra configuring on the klipper side.

Here is the documentation: https://moonraker.readthedocs.io/en/latest/configuration/#wled

Frix-x commented 1 year ago

There is currently no management of WLED in Klippain.

But as everything is customization, I would say it's possible to do it: my recommendation would be to override the STATUS_LEDS macro by copy/pasting all its content in the overrides.cfg file and adding in it some logic to also call WLED_ON string=xxxx preset=yyy as you want it.

s0ybean commented 1 year ago

thank you for the reply! :)

So, a quick way to do this would be to add this to add this in override:


[gcode_macro WLED_ON]
description: Turn WLED strip on using optional preset and resets led colors
gcode:
  {% set strip = params.STRIP|default("chamber")|string %}
  {% set preset = params.PRESET|default(4)|int %}

  {action_call_remote_method("set_wled_state",
                             strip=strip,
                             state=True,
                             preset=preset)}

[gcode_macro STATUS_LEDS]
    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_caselight_enabled %}
        WLED_ON STRIP="chamber" PRESET={status_color[color].caselight} TRANSMIT=1
    {% endif %}

and change this in variables:

'caselight': {
            'busy': {1},
            'cleaning': {2},
            'calibrating_z': {'3},
            'heating': {4},
            'homing': {5},
            'leveling': {6},
            'meshing': {7},
            'on': {8},
            'off': {9},
            'printing': {10},
            'standby': {11},
            'error': {12},
        },

it will then use preset value for caselight on my WLED instead of RGB value? am i on the right path?

s0ybean commented 1 year ago

this is where I am so far. I hope I am on the right track, but I am having a hard time figuring out how to get my WLED_ON macro to pull the number from my chamber variable and use it for preset. I'm really bad with variables, especially since this original one is a bit tricky since it accommodates a lot of different setups

i tried to copy how it was done for caselight, but change "color" to "preset" in override and just use the single number set in my variable config file instead of an rgb string

[gcode_macro _USER_VARIABLES]
variable_status_leds_chamber_enabled = True
variable_status_leds_chamber_led_name: "chamber"
gcode:
[gcode_macro WLED_ON]
description: Turn WLED strip on using optional preset and resets led colors
gcode:
  {% set leds_name = params.LEDS %}
  {% set color_name = params.COLOR %}
  {% set strip = params.STRIP|default("chamber")|string %}
  {% set preset = printer["gcode_macro _USER_VARIABLES"].status_leds_colors[leds_name][color_name] %}

  {action_call_remote_method("set_wled_state",
                             strip=strip,
                             state=True,
                             preset=preset)}
[gcode_macro STATUS_LEDS]
gcode:
    {% set color = params.COLOR|default('off')|lower %}

    {% set status_color = {
        'ready': {
            'logo': 'standby',
            'nozzle': 'standby',
            'caselight': 'standby',
            'chamber': 'standby',
            'minidisplay': 'on'
        },

 i added "chamber" entry for every status color

    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_chamber_enabled %}
        WLED_ON STRIP=chamber PRESET={status_color[color].chamber}
    {% endif %}**

in variables I did this:

        },
        'chamber': {
            'busy': 1,
            'cleaning': 1,
            'calibrating_z': 1,
            'heating': 1,
            'homing': 1,
            'leveling': 1,
            'meshing': 1,
            'on': 1,
            'off': 1,
            'printing': 1,
            'standby': 1,
            'error': 1,
        },
Frix-x commented 1 year ago

Hey how is it going? Did you managed to make it work?

I just had a look at your macros and it looks ok to me. At least it's how I would do it myself :)

s0ybean commented 1 year ago

Hi!

Unfortunately, it is not reading the variable I am using for preset. Not sure if I need " or ' or {} around the single number?

s0ybean commented 1 year ago

UndefinedError: dict object has no element Undefined

Surion79 commented 1 year ago

have you completed it or do you have still issues?

s0ybean commented 1 year ago

i'm stuck. was never able to figure out how to feed the variable properly

Surion79 commented 1 year ago

can you put here the whole picture? all gcode and config you use for the implementation? not only snippets

s0ybean commented 1 year ago

to summarize -- the goal is to, for example, have STATUS_LEDS COLOR="PRINTING" send the command WLED_ON preset=1, STATUS_LEDS COLOR="BUSY" sends command WLED_ON preset=2, etc.

It should pick up the preset number from variables.cfg since i set a variable_status_leds_colors for WLED ('chamber'). For testing, all of my led colors are set to 1.

the documentation for using wled is located here https://moonraker.readthedocs.io/en/latest/configuration/#wled

If i test wled by sending manual commands or setting a startup preset, it works properly, so i definitely have a connection to it.

thank you!

attached are my variables.cfg and overrides.cfg files. overrides.txt variables.txt

quoted are my relevant variables.cfg and overrides.cfg changes (excluding motor overrides) for quick reference:

################################
# WLED                         #
################################
[gcode_macro _USER_VARIABLES]
variable_status_leds_chamber_enabled = True
variable_status_leds_chamber_led_name: "chamber"
gcode:

[gcode_macro WLED_ON]
description: Turn WLED strip on using optional preset and resets led colors
gcode:
#  {% set leds_name 
    {% set leds_name = params.LEDS %}
    {% set color_name = params.COLOR %}
    {% set strip = params.STRIP|default('chamber')|lower %}
    {% set preset = printer["gcode_macro _USER_VARIABLES"].status_leds_colors[leds_name][color_name] %}

    {action_call_remote_method("set_wled_state",
                             strip=strip,
                             state=True,
                             preset=preset)}

[gcode_macro _SET_ALLLEDS_BY_NAME]
# set same color for all leds
gcode:
    {% set leds_name = params.LEDS %}
    {% set color_name = params.COLOR %}
    {% set led = printer["gcode_macro _USER_VARIABLES"]["status_leds_" + leds_name + "_led_name"] %}
    {% set color = printer["gcode_macro _USER_VARIABLES"].status_leds_colors[leds_name][color_name] %}
    {% set transmit = params.TRANSMIT|default(1) %}

    SET_LED LED={led} RED={color.r} GREEN={color.g} BLUE={color.b} WHITE={color.w}  TRANSMIT={transmit}

[gcode_macro STATUS_LEDS]
gcode:
    {% set color = params.COLOR|default('off')|lower %}

    {% set status_color = {
        'ready': {
            'logo': 'standby',
            'nozzle': 'standby',
            'caselight': 'standby',
            'chamber': 'standby',
            'minidisplay': 'on'
        },
        'busy': {
            'logo': 'busy',
            'nozzle': 'on',
            'caselight': 'busy',
            'chamber': 'busy',
            'minidisplay': 'on'
        },
        'heating': {
            'logo': 'heating',
            'nozzle': 'heating',
            'caselight': 'heating',
            'chamber': 'heating',
            'minidisplay': 'on'
        },
        'leveling': {
            'logo': 'leveling',
            'nozzle': 'on',
            'caselight': 'leveling',
            'chamber': 'leveling',
            'minidisplay': 'on'
        },
        'homing': {
            'logo': 'homing',
            'nozzle': 'on',
            'caselight': 'homing',
            'chamber': 'homing',
            'minidisplay': 'on'
        },
        'cleaning': {
            'logo': 'cleaning',
            'nozzle': 'on',
            'caselight': 'cleaning',
            'chamber': 'cleaning',
            'minidisplay': 'on'
        },
        'meshing': {
            'logo': 'meshing',
            'nozzle': 'on',
            'caselight': 'meshing',
            'chamber': 'meshing',
            'minidisplay': 'on'
        },
        'calibrating_z': {
            'logo': 'calibrating_z',
            'nozzle': 'on',
            'caselight': 'calibrating_z',
            'chamber': 'calibrating_z',
            'minidisplay': 'on'
        },
        'printing': {
            'logo': 'printing',
            'nozzle': 'on',
            'caselight': 'printing',
            'chamber': 'printing',
            'minidisplay': 'on'
        },
        'off': {
            'logo': 'off',
            'nozzle': 'off',
            'caselight': 'off',
            'chamber': 'off',
            'minidisplay': 'off'
        },
        'on': {
            'logo': 'on',
            'nozzle': 'on',
            'caselight': 'on',
            'chamber': 'on',
            'minidisplay': 'on'
        },        
        'error': {
            'logo': 'error',
            'nozzle': 'error',
            'caselight': 'error',
            'chamber': 'error',
            'minidisplay': 'error'
        }   
    } %}

    {% if not (color in status_color) %}
        { action_raise_error("COLOR is not valid!") }
    {% endif %}

    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_enabled %}
        _SET_LEDS_BY_NAME LEDS="logo" COLOR={status_color[color].logo} TRANSMIT=0
        _SET_LEDS_BY_NAME LEDS="nozzle" COLOR={status_color[color].nozzle} TRANSMIT=1
    {% endif %}

    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_caselight_enabled %}
        _SET_ALLLEDS_BY_NAME LEDS="caselight" COLOR={status_color[color].caselight} TRANSMIT=1
    {% endif %}

    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_chamber_enabled %}
        WLED_ON STRIP=chamber PRESET={status_color[color].chamber}
    {% endif %}

    {% if printer["gcode_macro _USER_VARIABLES"].status_leds_minidisplay_enabled %}
        _SET_ALLLEDS_BY_NAME LEDS="minidisplay" COLOR={status_color[color].minidisplay} TRANSMIT=1
    {% endif %}

################################################
# Other hardware options used in the macros
################################################

## Brush and purge bucket available in the machine
## If this is not available in the machine, set both positions
## variables to "-1, -1, -1" for safety
variable_purge_and_brush_enabled: False
variable_force_homing_before_brush: False # Add an homing of the Z axis before a clean to be sure to not miss the brush
variable_brush_over_y_axis: True # Cleanup is done moving the extruder along the Y axis, then X axis. If false, only X axis is done
variable_brush_xyz: -1, -1, -1 # Position of the brush center for nozzle cleaning
variable_purge_bucket_xyz: -1, -1, -1 # Purge bucket position
variable_purge_distance: 30 # Amount to purge

## Servo angles used to define the retracted and deployed positions
## of the purge bucket and brush (if applicable). These variables are only used if a purge
## bucket servo is included in the config and have no effect if it's not the case
variable_purgeclean_servo_angle_retracted: 0
variable_purgeclean_servo_angle_deployed: 90

## White light parameters (if installed in the machine)
variable_light_intensity_start_print: 100
variable_light_intensity_printing: 30
variable_light_intensity_end_print: 0

## Fix the M190/M109 commands to avoid some wait time while the temperature
## settle on very low thermal latency devices (such as the BambuLabs hotend)
variable_fix_heaters_temperature_settle: False

## SteathBurner minidisplay and case leds colors (if installed in the machine)
variable_status_leds_colors: {
        'logo': {
            'busy': {'r': 0.4, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'cleaning': {'r': 0.0, 'g': 0.02, 'b': 0.5, 'w': 0.0},
            'calibrating_z': {'r': 0.8, 'g': 0., 'b': 0.35, 'w': 0.0},
            'heating': {'r': 0.3, 'g': 0.18, 'b': 0.0, 'w': 0.0},
            'homing': {'r': 0.0, 'g': 0.6, 'b': 0.2, 'w': 0.0},
            'leveling': {'r': 0.5, 'g': 0.1, 'b': 0.4, 'w': 0.0},
            'meshing': {'r': 0.2, 'g': 1.0, 'b': 0.0, 'w': 0.0},
            'on': {'r': 0.8, 'g': 0.8, 'b': 0.8, 'w':1.0},                                        
            'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'printing': {'r': 1.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'standby': {'r': 0.01, 'g': 0.01, 'b': 0.01, 'w': 0.1},
            'error': {'r': 0.6, 'g': 0.0, 'b': 0.0, 'w':0.0},
        },
        'nozzle': {
            'heating': {'r': 0.8, 'g': 0.35, 'b': 0.0, 'w':0.0},
            'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'on': {'r': 0.8, 'g': 0.8, 'b': 0.8, 'w':1.0},
            'standby': {'r': 0.6, 'g': 0.0, 'b': 0.0, 'w':0.0},
            'error': {'r': 0.6, 'g': 0.0, 'b': 0.0, 'w':0.0},
        },
        'caselight': {
            'busy': {'r': 0.4, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'cleaning': {'r': 0.0, 'g': 0.02, 'b': 0.5, 'w': 0.0},
            'calibrating_z': {'r': 0.8, 'g': 0., 'b': 0.35, 'w': 0.0},
            'heating': {'r': 0.3, 'g': 0.18, 'b': 0.0, 'w': 0.0},
            'homing': {'r': 0.0, 'g': 0.6, 'b': 0.2, 'w': 0.0},
            'leveling': {'r': 0.5, 'g': 0.1, 'b': 0.4, 'w': 0.0},
            'meshing': {'r': 0.2, 'g': 1.0, 'b': 0.0, 'w': 0.0},
            'on': {'r': 0.8, 'g': 0.8, 'b': 0.8, 'w':1.0},
            'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'printing': {'r': 1.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'standby': {'r': 0.01, 'g': 0.01, 'b': 0.01, 'w': 0.1},
            'error': {'r': 0.6, 'g': 0.0, 'b': 0.0, 'w':0.0},
        },
        'chamber': {
            'busy': 1,
            'cleaning': 1,
            'calibrating_z': 1,
            'heating': 1,
            'homing': 1,
            'leveling': 1,
            'meshing': 1,
            'on': 1,
            'off': 1,
            'printing': 1,
            'standby': 1,
            'error': 1,
        },
        'minidisplay': {
            'on': {'r': 0.0, 'g': 0.2, 'b': 0.4, 'w':1.0},
            'off': {'r': 0.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'error': {'r': 0.4, 'g': 0.0, 'b': 0.0, 'w':0.0},
        },         
        'thermal': {
            'hot': {'r': 1.0, 'g': 0.0, 'b': 0.0, 'w': 0.0},
            'cold': {'r': 0.3, 'g': 0.0, 'b': 0.3, 'w': 0.0}
        }
    }

## Do not remove the next lines
gcode:

[save_variables]
filename: ~/printer_data/config/save_variables.cfg
Frix-x commented 9 months ago

I changed the title of this issue to track WLED but also Led_effect integration since it's highly linked and there is still currently no good implementation of this into Klippain... This issue can also track rainbow barf integration as well

smwoodward commented 8 months ago

I don't have anything for WLED integration, but I am working on BARF and I think I have it configured for the most part. Would you want to create another branch for me to send the PR to to help look over it?

smwoodward commented 8 months ago

https://github.com/Frix-x/klippain/pull/400

Surion79 commented 8 months ago

imho the pr needs major work done

Frix-x commented 6 months ago

This is now merged on develop to be released soon :)