Klipper: Feature request: multiple FAN definitions and linking to active extruder

Created on 14 Nov 2019  路  20Comments  路  Source: KevinOConnor/klipper

Back with my tool-changing printer. Klipper only supports one part cooling fan. I intend to have multiple tools, each with their own fans. The heatsink fans i will manage with [heater_fan ].

My only option right now is to have a relay and switch the part cooling fan wires to different fans for each tool, but i would need 10 relays and a rats nest of wires.

Could the feature be implemented in klipper? Or at least to allow multiple fans and a gcode command to switch fans or select a number of fans to work ? I would add this gcode command in my toolchange macros.

Thank you

Most helpful comment

For others looking for a solution to IDEX part cooling fans, this how I solved it for my printer.
First you comment out [fan] section and then configure the sections below and the macros.

[output_pin fan0]
pin: PC8
pwm: True
cycle_time: 0.0100
hardware_pwm: false
value: 0.05
scale: 255
shutdown_value: 0.0

[output_pin fan1]
pin: PE5
pwm: True
cycle_time: 0.0100
hardware_pwm: false
value: 0.05
scale: 255
shutdown_value: 0.0

[gcode_macro M106]
gcode:
    {% if params.P is defined %}
      {% if params.S is defined %}
        SET_PIN PIN=fan{params.P|int} VALUE={params.S|int}
      {% else %}
        SET_PIN PIN=fan{params.P|int} VALUE=255
      {% endif %}
    {% else %}
      {% if params.S is defined %}
        SET_PIN PIN=fan0 VALUE={params.S|int}
      {% else %}
        SET_PIN PIN=fan0 VALUE=255        
      {% endif %}
    {% endif %}

[gcode_macro M107]
gcode:
    {% if params.P is defined %}
      SET_PIN PIN=fan{params.P|int} VALUE=0      
    {% else %}
      SET_PIN PIN=fan0 VALUE=0
      SET_PIN PIN=fan1 VALUE=0      
    {% endif %}

Hope it helps and thank you for the awesome firmware klipper-team :)

All 20 comments

Hi @vladbabii,

It did not look like there was a Klipper log file attached to this ticket. The log file has been engineered to answer common questions the Klipper developers have about the software and its environment (software version, hardware type, configuration, event timing, and hundreds of other questions).

Unfortunately, too many people have opened tickets without providing the log. That consumes developer time; time that would be better spent enhancing the software. If this ticket references an event that has occurred while running the software then the Klipper log must be attached to this ticket. Otherwise, this ticket will be automatically closed in a few days.

For information on obtaining the Klipper log file see: https://github.com/KevinOConnor/klipper/blob/master/docs/Contact.md

The log can still be attached to this ticket - just add a comment and attach the log to that comment.

Best regards,
~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

It is possible to use a "multi_pin" config module to route a single virtual pin to multiple output pins.

It's also possible to create "output_pin" config sections for each fan, and then set the fan speed manually with SET_PIN commands.

It's also possible (though cumbersome) to define each fan as an output_pin, not define a regular "fan" section, and then write an M106 macro that determines which pin to update on SET_PIN.

Otherwise, a developer would likely need to implement what you are requesting.

-Kevin

@KevinOConnor so i can override gcode command with [gcode_macro M106] ? then put some jinja template code to run pwm to the correct fan? This would be most useful, since i could set the corect pwm to a new tool when picking it up and stopping the old tool fan.

You can not override a builtin command. However, if there is no [fan] config section then M106/M107 is not registered (at least on the latest version of Klipper) and thus you can define your own M106/M107 macros.

-Kevin

@KevinOConnor the way M106 is used is like this

M106 [P<index>] [S<speed>]

But gcode_macro would work with something like this as far as i know:

M106 P=1 S=120

or would defining a gcode variable P would work with P ?

If one creates a gcode_macro for a "traditional g-code" command then it takes traditional g-code parameter syntax (eg, M106 P1 S120).

-Kevin

@KevinOConnor i removed the [fan] section but get an error the M106 command is already defined. The definitions for M106 is around line 480-492

Config error
Traceback (most recent call last):
  File "/opt/klipper/klippy/klippy.py", line 134, in _connect
    self._read_config()
  File "/opt/klipper/klippy/klippy.py", line 127, in _read_config
    self.try_load_module(config, section_config.get_name())
  File "/opt/klipper/klippy/klippy.py", line 116, in try_load_module
    self.objects[section] = init_func(config.getsection(section))
  File "/opt/klipper/klippy/extras/gcode_macro.py", line 152, in load_config_prefix
    return GCodeMacro(config)
  File "/opt/klipper/klippy/extras/gcode_macro.py", line 99, in __init__
    self.gcode.register_command(self.alias, self.cmd, desc=self.cmd_desc)
  File "/opt/klipper/klippy/gcode.py", line 71, in register_command
    "gcode command %s already registered" % (cmd,))
Error: gcode command M106 already registered
gcode command M106 already registered

k1.zip

You'll have to go up to the latest version of the code (which includes commit e0e2f154).

-Kevin

Any chance of getting a command override with a rename of the old command ?

[gcode_override M106]
rename_original: XM106
gcode:
  DO_STUFF
[gcode_macro fan_config]
variable_toolindex: 0
variable_speed: 0
gcode:
   RESPOND PREFIX="info" MSG="Macro > Fan config > ok"

[gcode_macro M106]
gcode:
  {% set fanspeed = 255 %}
  {% if params.S is defined %}
    {% set fanspeed = params.S|int %}
  {% endif %}
  {% if fanspeed < 0 %}
    {% set fanspeed = 0 %}
  {% endif %}
  {% if fanspeed > 255 %}
    {% set fanspeed = 255 %}
  {% endif %}
  RESPOND PREFIX="info" MSG="Macro > M106 > speed {fanspeed}"
  FANSPEED SPEED={fanspeed}

[gcode_macro M107]
gcode:
  RESPOND PREFIX="info" MSG="Macro > M107 > speed 0"
  FANSPEED SPEED=0

[gcode_macro FANSPEED]
default_parameter_SPEED: 255
gcode:
  RESPOND PREFIX="info" MSG="Macro > fanspeed > SET FAN to { params.SPEED|int }"
  SET_GCODE_VARIABLE MACRO=fan_config VARIABLE=speed VALUE={ params.SPEED|int }

Now i just need to play around with the SET_PIN command.
Thank you!

Late to the party, but would it be possible to just add and index or something to the fan definitions so if the index is included in the M106 command it targets the fan wit the matching index?

Example with a single fan

[gcode_macro fan_config]
variable_toolindex: 0
variable_speed: 0
gcode:
   RESPOND PREFIX="info" MSG="Macro > Fan config > ok"

[gcode_macro M106]
gcode:
  {% set fanspeed = 255 %}
  {% if params.S is defined %}
    {% set fanspeed = params.S|int %}
  {% endif %}
  {% if fanspeed < 0 %}
    {% set fanspeed = 0 %}
  {% endif %}
  {% if fanspeed > 255 %}
    {% set fanspeed = 255 %}
  {% endif %}
  RESPOND PREFIX="info" MSG="Macro > M106 > speed {fanspeed}"
  FANSPEED SPEED={fanspeed}

[gcode_macro M107]
gcode:
  RESPOND PREFIX="info" MSG="Macro > M107 > speed 0"
  FANSPEED SPEED=0

[gcode_macro FANSPEED]
default_parameter_SPEED: 255
gcode:
  RESPOND PREFIX="info" MSG="Macro > fanspeed > SET FAN to { params.SPEED|int }"
  SET_GCODE_VARIABLE MACRO=fan_config VARIABLE=speed VALUE={ params.SPEED|int }

  {% if params.SPEED is defined %}

    {% if params.SPEED|int == 255 %}
      {% set realspeed = 1 %}
    {% else %}
      {% if params.SPEED|int == 0 %}
        {% set realspeed = 0 %}
      {% else %}
        {% set realspeed = 0.003921*params.SPEED|int %}
      {% endif %}
    {% endif %}

  {% else %}

    {% set realspeed = 0 %}

  {% endif %}

  RESPOND PREFIX="info" MSG="Macro > fanspeed > SET FAN realspeed to {realspeed}"
  SET_PIN PIN=fan_0 VALUE={realspeed}

[output_pin fan_0]
pin: z:PC9
pwm: True
value: 0
shutdown_value: 0

@timmit99 you want to change fan_0 to some specific fan. If you have "fan_0" to "fan_5" output pins you could change the last line in the FANSPEED macro with

SET_PIN PIN=fan_{params.S|int} VALUE={realspeed}

but you'd also need to modify M106 and M107 to check for correct S value

Okay, I'm going to close this as it looks like a solution was found for the original issue.

-Kevin

I think a solution like this would be simpler.

https://github.com/KevinOConnor/klipper/issues/2351

@vladbabii I'm sorry, programming isn't really my thing. Does your code take care of your original issue (controlling multiple fans on multiple tools)? I need to do the same thing on my tool changer but your code looks a little incomplete for that purpose and i'm not competent enough to finish it to work with more than 1 fan. Did you actually get something implemented on your machine that works?

@tjsc5f

If you replace the line with

SET_PIN PIN=fan_0 VALUE={realspeed}

and change fan_0 to a tools fan name then it will work.

I am working on a toolchanging macro to integrate this (and many other things).

https://github.com/vladbabii/3d_printed_toolchanger/blob/master/macros/toolchanger_v3/tool_pp.cfg

Give me a couple of days and i will post the new version, busy with work at the moment.

@vladbabii

Just an FYI, if you use scale: 255 at your output_pin definitions, you can get away without calculating the actual pin_value within the macro.

You may still want to check if the supplied speed-value is out of bounds, but it can be as simple as this

[gcode_macro SET_TOOL_FAN]
gcode:
  SET_PIN PIN=fan_{printer.toolhead.extruder} VALUE={params.SPEED|int}
  SET_GCODE_VARIABLE MACRO=TOOL_FAN_STATE VARIABLE=speed VALUE={params.SPEED|int}

[output_pin fan_extruder]
pin: PC21
pwm: True
value: 0
shutdown_value: 0
scale: 255

[output_pin fan_extruder1]
pin: PD7
pwm: True
value: 0
shutdown_value: 0
scale: 255

I have similar macros for other things so i just copy-pasted and modified some numbers. Thanks for the shorter version.

For others looking for a solution to IDEX part cooling fans, this how I solved it for my printer.
First you comment out [fan] section and then configure the sections below and the macros.

[output_pin fan0]
pin: PC8
pwm: True
cycle_time: 0.0100
hardware_pwm: false
value: 0.05
scale: 255
shutdown_value: 0.0

[output_pin fan1]
pin: PE5
pwm: True
cycle_time: 0.0100
hardware_pwm: false
value: 0.05
scale: 255
shutdown_value: 0.0

[gcode_macro M106]
gcode:
    {% if params.P is defined %}
      {% if params.S is defined %}
        SET_PIN PIN=fan{params.P|int} VALUE={params.S|int}
      {% else %}
        SET_PIN PIN=fan{params.P|int} VALUE=255
      {% endif %}
    {% else %}
      {% if params.S is defined %}
        SET_PIN PIN=fan0 VALUE={params.S|int}
      {% else %}
        SET_PIN PIN=fan0 VALUE=255        
      {% endif %}
    {% endif %}

[gcode_macro M107]
gcode:
    {% if params.P is defined %}
      SET_PIN PIN=fan{params.P|int} VALUE=0      
    {% else %}
      SET_PIN PIN=fan0 VALUE=0
      SET_PIN PIN=fan1 VALUE=0      
    {% endif %}

Hope it helps and thank you for the awesome firmware klipper-team :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jannoke picture jannoke  路  3Comments

ChiliApple picture ChiliApple  路  4Comments

krpepe picture krpepe  路  5Comments

leungtech picture leungtech  路  4Comments

TronskiFPV picture TronskiFPV  路  5Comments