Skip to content

feat: add auxiliary part cooling fan support - #805

Open
ndotzbgt wants to merge 1 commit into
Frix-x:mainfrom
ndotzbgt:feat/aux-fan-part-cooling
Open

ndotzbgt wants to merge 1 commit into
Frix-x:mainfrom
ndotzbgt:feat/aux-fan-part-cooling

Conversation

@ndotzbgt

Copy link
Copy Markdown

Summary

Adds an independently controlled secondary part cooling fan (e.g. the OrcaSlicer "Auxiliary Part Cooling Fan", addressed as M106 P2 / M107 P2), complementing the existing PART_FAN.

Changes

  • Hardware configs (config/hardware/fans/): aux_fan.cfg and aux_fan_tachometer.cfg (the latter adds AUX_FAN_TACHO monitoring with the same safety checks as the base fans). Wired pins use the new AUX_FAN / AUX_FAN_TACHO board_pins aliases.
  • Control macros (macros/hardware_functions/aux_fan.cfg): START_AUX_FAN / STOP_AUX_FAN, a delayed stop macro, the tachometer background check loop, and an M106 / M107 override that forwards P2 to the aux fan and keeps P0 / bare calls fully compatible with existing slicers.
  • Print flow integration:
    • start_print: vent the chamber if it is above the configured temperature before heating, and optionally spread heat during the soak.
    • end_print / cancel_print: optional post-print run-down to cool the bed faster and help recirculating filters/exhaust.
    • control: clean shutdown on PRINT_STOP.
  • Variables & docs: new variable_aux_fan_* settings in variables.cfg, include lines in printer.cfg, and AUX_FAN / AUX_FAN_TACHO pinout documentation.

Validation

Added a CI pipeline: tests/lint_jinja.py syntax-checks every templated block with Klipper's own Jinja2 environment, and tests/config_check.py assembles a full reference config and loads it with a real klippy (standard and aux-fan-tachometer variants), run by .github/workflows/validate.yml.

Verified locally: 279/279 templates pass, both klippy config loads pass (only the expected "no MCU connected" step fails), and an injected broken template fails the checks.

Enabling

Uncomment [include config/hardware/fans/aux_fan.cfg] (or aux_fan_tachometer.cfg) in user_templates/printer.cfg, define AUX_FAN (and optionally AUX_FAN_TACHO) pins in mcu.cfg, and tune the variable_aux_fan_* settings in user_templates/variables.cfg.

@mjonuschat

Copy link
Copy Markdown
Collaborator

Thank you for your contribution. I see a few problems with this PR:

  1. Separation of concerns, it's doing too much. You've added the aux fan feature, a jinja template linter, a config checker and a CI pipeline under the guise of the aux fan. These should should be at least two, maybe three PRs. Especially given how heavy the config checker is.
  2. There's a number of bugs in the aux fan implementation:
    1. fan monitoring seems to get disable before later end print block that runs the fan for a while
    2. The M106 rename only works when the user included a [fan] block - that is a separate and optional component - hotends like the Chube conduction don't require one, so this is brittle
    3. aux_fan_soak_speed seems to conflict the the hardcoded min_rpm
    4. there's a disconnect between _MODULE_HEATSOAK_BED and _MODULE_HEATSOAK_CHAMBER - they are independent, the fan might never get stopped
    5. CURRENT_CHAMBER_TEMP > aux_fan_vent_temp triggers on room temp with the current defaults, leading to a 2 min delay for everyone, no matter if they opted in.
    6. the start routinge also seems to skip tach monitoring

@mjonuschat

Copy link
Copy Markdown
Collaborator

Hey, it looks like there are still some of the bugs I mentioned earlier open in this pull request and the new design with every file that has a [fan] section requiring an include is quite brittle and a maintenance burden for every future board we want to add.

And same as the other changes you had in before, the axis twist compensation needs to be in a separate PR

@ndotzbgt
ndotzbgt force-pushed the feat/aux-fan-part-cooling branch from a7a5377 to 933109c Compare August 22, 2026 03:08
@mjonuschat

Copy link
Copy Markdown
Collaborator

A few things still worth addressing:

  • CI should be its own PR
    The lint/config check infra looks useful and would be easier to review and merge on its own.
  • Blocking G4 vent
    When the vent is enabled, G4 P{aux_fan_vent_time * 1000} blocks for up to 2 minutes with no progress feedback. At the bare minimum a status message on start would be required, a loop with status messages would be more consistent with how the chamber soak works.
  • Tach thresholds
    The proportional RPM scaling is a big improvement, but min_rpm_max, min_rpm_floor, and max_consecutive_stops are still hardcoded. Different fans have very different RPM ranges, the RPM bounds should be _USER_VARIABLES entries.
  • Include order dependency
    fan_bridge.cfg M106 loads first (via part_fan.cfg), then aux_fan.cfg M106 overrides it. It works, but correctness depends on printer.cfg ordering that isn't documented. Worth a comment in the template.
  • Possible typo in tests/config_check.py: firmware_rectraction.cfg should be firmware_retraction.cfg?
  • Nit: Missing EOF newlines in 5 files (validate.yml, aux_fan.cfg, aux_fan_tachometer.cfg, config_check.py, lint_jinja.py).

Overall heading in a good direction 👍

@mjonuschat

Copy link
Copy Markdown
Collaborator

Looking almost ready. The vent countdown loop, configurable tach thresholds, and include order docs are all solid improvements. A few things left:

  • Split CI and typo fixes into separate PRs.
    The core aux fan is ~300 lines across about a dozen files, but the PR is 51 files / 882 lines with CI (~477 lines) and 36 unrelated typo-fix files bundled in. Three focused PRs would each be easy to review and merge.
  • Make the tach poll interval a variable. DURATION=3 in _BACKGROUND_AUX_TACHO_CHECK is the last hardcoded tach value. The stoppage message also hardcodes *3 in the timing math — if someone changes the interval, those messages become wrong.
  • Missing EOF newline in config/hardware/fans/aux_fan.cfg (last one remaining).

@mjonuschat

Copy link
Copy Markdown
Collaborator

Hey, thanks for the continued work on this! Before the next push, could we step back and align on the scope of this PR? It's grown quite a bit, we're at 80+ files and ~4,500 lines now, and it's getting hard to review as a single unit.

Right now the PR bundles several independent changes alongside the aux fan feature:

  • CI/testing pipeline — validate.yml, lint_jinja.py, config_check.py, test_fan_conf_check.py
  • Post-update orchestrator — update_sync_variables.py, update_detect_modules.py, update_changelog_digest.py, update_postprocess.py, klippain_update_notify.sh, shell_commands.cfg, and their tests
  • Typo fixes across ~36 files ("overide" → "override", "hesistate" → "hesitate", etc.)

Each of these would be easier-to-review PR on its own. Please split them out so this PR stays focused on the aux fan support? That'll make it much easier to get through review and toward a merge.

@mjonuschat

Copy link
Copy Markdown
Collaborator

Looking at the changes to the installer and README (the "What makes this fork different" section, the version bump to 1.5, the post-update orchestrator), it seems like this may have evolved into its own fork of Klippain?

If so, should we close this PR out, or is the aux fan feature still intended for upstream?

@ndotzbgt

ndotzbgt commented Sep 3, 2026

Copy link
Copy Markdown
Author

Hey, thanks for the continued work on this! Before the next push, could we step back and align on the scope of this PR? It's grown quite a bit, we're at 80+ files and ~4,500 lines now, and it's getting hard to review as a single unit.

Right now the PR bundles several independent changes alongside the aux fan feature:

* CI/testing pipeline — validate.yml, lint_jinja.py, config_check.py, test_fan_conf_check.py

* Post-update orchestrator — update_sync_variables.py, update_detect_modules.py, update_changelog_digest.py, update_postprocess.py, klippain_update_notify.sh, shell_commands.cfg, and their tests

* Typo fixes across ~36 files ("overide" → "override", "hesistate" → "hesitate", etc.)

Each of these would be easier-to-review PR on its own. Please split them out so this PR stays focused on the aux fan support? That'll make it much easier to get through review and toward a merge.

splittiing the work currently aux fan cooling intended to be used on the upstream

@ndotzbgt
ndotzbgt force-pushed the feat/aux-fan-part-cooling branch from d810daf to 24ddba9 Compare September 3, 2026 12:01
Add an independent secondary part cooling fan (AUX_FAN) with:

- Hardware configs: aux_fan.cfg (basic) and aux_fan_tachometer.cfg
  (with tachometer monitoring)
- fan_bridge.cfg: OrcaSlicer M106 P2 / M107 P2 bridge via
  rename_existing, included from part_fan.cfg and toolhead boards
- Macros: START_AUX_FAN, STOP_AUX_FAN, tachometer safety loop
  (proportional min_rpm scaling with configurable poll interval)
- Print flow integration:
  - START_PRINT: chamber venting with status messages, aux fan stop
    from previous run-down, tach monitoring start
  - END_PRINT/CANCEL_PRINT: post-print run-down with configurable
    speed/time, tach re-enabled before fan start
  - _MODULE_HEATSOAK_BED: aux fan for heat spreading, stopped at end
  - M84: aux fan stop removed (now in end_print/cancel_print)
- Startup validation (_INIT_CHECKFANCONF): detects missing
  fan_bridge.cfg when [fan] + gcode M106 exist but M106.1 absent
- Config check CI: standard + tachometer variants, lint_jinja.py,
  test_fan_conf_check.py for M106 fallback logic
- Variables: aux_fan_enabled, aux_fan_name, aux_fan_tach_enabled,
  aux_fan_tach_poll_interval, aux_fan_tach_min_rpm_max/floor,
  aux_fan_tach_max_consecutive_stops, aux_fan_vent_temp/speed/time,
  aux_fan_vent_status_interval, aux_fan_soak_speed,
  aux_fan_speed_on_end_print, aux_fan_time_on_end_print
@ndotzbgt
ndotzbgt force-pushed the feat/aux-fan-part-cooling branch from 24ddba9 to e1193a9 Compare September 3, 2026 19:12
@mjonuschat

Copy link
Copy Markdown
Collaborator

The split looks good, a few small things left open that I can see:

  • README fork section: the "What makes this fork different" block and the "Note for users of this fork" (telling users to install from ndotzbgt/klippain) don't belong in upstream. If this is intended for Frix-x/klippain, that section has to go.
  • CI half-in, half-out: the three test files are still here but .github/workflows/validate.yml is not. Let's drop these remaining files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants