Skip to content

Instantly share code, notes, and snippets.

@cdracars
Created June 21, 2025 14:49
Show Gist options
  • Save cdracars/659efe80ad43d71e0e72ff013d2ccd9d to your computer and use it in GitHub Desktop.
Save cdracars/659efe80ad43d71e0e72ff013d2ccd9d to your computer and use it in GitHub Desktop.
# ============================================================================
# KLIPPER HEAT SOAK MACRO
# ============================================================================
#
# A comprehensive heat soak macro for Klipper 3D printers that heats the bed
# to a target temperature and maintains it for a specified duration to warm
# the printer chamber/enclosure for materials like ABS, ASA, PC, etc.
#
# Features:
# - Configurable bed temperature and soak duration
# - Optional part cooling fan for air circulation
# - Progress updates with countdown timer
# - Small toolhead movements for air circulation
# - Audio feedback on completion
# - Compatible with printers that have G4 timing issues
#
# Usage Examples:
# HEAT_SOAK ; Default: 100°C for 15 minutes
# HEAT_SOAK BED_TEMP=110 ; Custom temperature
# HEAT_SOAK BED_TEMP=100 SOAK_TIME=1800 ; 30 minute soak
# HEAT_SOAK BED_TEMP=110 FAN_SPEED=192 ; High fan speed (75%)
# HEAT_SOAK BED_TEMP=80 SOAK_TIME=600 FAN_SPEED=0 ; No fan, 10 minutes
#
# Author: Cody Dracars
# Date: 2025-04-05
# License: MIT
# GitHub Gist: https://gist.github.com/cdracars/klipper-heat-soak-macro
#
# Tested on: Sovol SV08 with enclosure, Klipper firmware
# Should work on: Any Klipper printer with heated bed
#
# ============================================================================
[gcode_macro HEAT_SOAK]
description: Heat bed and soak chamber for high-temp materials
gcode:
# ========================================================================
# PARAMETER PROCESSING
# ========================================================================
# Parse input parameters with sensible defaults
# BED_TEMP: Target bed temperature in Celsius (default: 100°C)
# SOAK_TIME: Soak duration in seconds (default: 900s = 15 minutes)
# FAN_SPEED: Part cooling fan speed 0-255 (default: 128 = 50%)
# ========================================================================
{% set bed_temp = params.BED_TEMP|default(100)|int %}
{% set soak_time = params.SOAK_TIME|default(900)|int %}
{% set fan_speed = params.FAN_SPEED|default(128)|int %}
# Calculate update intervals (every 30 seconds for progress updates)
{% set update_interval = 30 %}
{% set num_updates = (soak_time // update_interval)|int %}
# Validate parameters to prevent issues
{% if bed_temp < 0 or bed_temp > 150 %}
{action_raise_error("BED_TEMP must be between 0-150°C")}
{% endif %}
{% if soak_time < 60 or soak_time > 7200 %}
{action_raise_error("SOAK_TIME must be between 60-7200 seconds (1 minute to 2 hours)")}
{% endif %}
{% if fan_speed < 0 or fan_speed > 255 %}
{action_raise_error("FAN_SPEED must be between 0-255")}
{% endif %}
# ========================================================================
# INITIAL SETUP AND HEATING
# ========================================================================
# Start heating the bed and prepare the printer for heat soak
# ========================================================================
M117 Heat Soak: Heating bed to {bed_temp}°C...
M118 Heat Soak: Starting bed heating to {bed_temp}°C
M118 Heat Soak: Soak duration will be {soak_time}s ({(soak_time/60)|round(1)} minutes)
M118 Heat Soak: Fan speed set to {fan_speed} ({(fan_speed/255*100)|round}%)
# Heat bed to target temperature and wait
M190 S{bed_temp} ; Set bed temperature and wait for it to reach target
# ========================================================================
# PRINTER POSITIONING
# ========================================================================
# Ensure printer is homed and position toolhead safely
# ========================================================================
# Home all axes if not already homed (safety check)
{% if printer.toolhead.homed_axes != "xyz" %}
M118 Heat Soak: Homing all axes...
G28 ; Home all axes
{% endif %}
# Switch to absolute positioning mode
G90
# Move toolhead to center and safe Z height for optimal air circulation
{% set center_x = printer.toolhead.axis_maximum.x / 2 %}
{% set center_y = printer.toolhead.axis_maximum.y / 2 %}
{% set safe_z = 10 %} ; 10mm above bed - safe but low enough for heating
G1 X{center_x} Y{center_y} Z{safe_z} F6000 ; Move to center position
# ========================================================================
# HEAT SOAK PROCESS
# ========================================================================
# Main heat soak loop with progress updates and air circulation
# ========================================================================
M117 Heat Soak: Starting {soak_time}s soak...
M118 Heat Soak: Beginning soak process
M118 Heat Soak: Use M112 (emergency stop) if you need to abort
# Turn on part cooling fan for air circulation (if specified)
{% if fan_speed > 0 %}
M106 S{fan_speed} ; Turn on part cooling fan
M118 Heat Soak: Part cooling fan enabled for air circulation
{% endif %}
# Main countdown loop - updates every 30 seconds
# NOTE: This uses loops of 1-second delays to work around G4 timing issues
# that some Klipper configurations experience with longer delays
{% for i in range(num_updates, 0, -1) %}
{% set remaining_time = i * update_interval %}
{% set remaining_minutes = (remaining_time / 60)|round(1) %}
# Display progress on printer screen and console
M117 Heat Soak: {remaining_time}s left ({remaining_minutes}min)
M118 Heat Soak: {remaining_time} seconds remaining
# Small toolhead movement for air circulation
# Alternates between two X positions to create gentle air movement
{% set movement_distance = 10 %} ; Move 10mm back and forth
{% set x_pos = center_x + ((i % 2) * movement_distance - movement_distance/2) %}
G1 X{x_pos} F3000 ; Slow movement to avoid vibration
# Wait for the update interval using multiple 1-second delays
# This approach works around timing issues with single long G4 commands
# that some Klipper configurations experience
{% for second in range(update_interval) %}
G4 P1000 ; Wait 1 second (P parameter uses milliseconds)
{% endfor %}
{% endfor %}
# ========================================================================
# COMPLETION AND CLEANUP
# ========================================================================
# Heat soak complete - clean up and notify user
# ========================================================================
# Turn off part cooling fan
M107 ; Fan off
# Move toolhead to a convenient position (front center, low)
G1 X{center_x} Y{printer.toolhead.axis_minimum.y + 10} Z{safe_z} F6000
# Update display and console
M117 Heat Soak: Complete! Chamber ready.
M118 Heat Soak: Process complete - chamber should be heated
M118 Heat Soak: Bed temperature: {bed_temp}°C maintained for {soak_time}s
# ========================================================================
# AUDIO FEEDBACK
# ========================================================================
# Provide audio notification that heat soak is complete
# NOTE: Requires [output_pin beeper] or BEEP macro to be configured
# ========================================================================
# Three-beep completion signal (if BEEP macro is available)
# Remove or comment out this section if you don't have a beeper configured
{% if 'gcode_macro BEEP' in printer %}
BEEP ; First beep
G4 P300 ; Short pause
BEEP ; Second beep
G4 P600 ; Longer pause
BEEP ; Final beep
M118 Heat Soak: Audio notification sent
{% else %}
M118 Heat Soak: No beeper configured - completion notification skipped
{% endif %}
# ========================================================================
# FINAL STATUS
# ========================================================================
M118 Heat Soak: Macro execution complete
M118 Heat Soak: Ready for high-temperature material printing
# ============================================================================
# INSTALLATION INSTRUCTIONS
# ============================================================================
#
# 1. Copy this entire macro to your Klipper configuration
# - Add to printer.cfg, or
# - Save as heat_soak.cfg and add [include heat_soak.cfg] to printer.cfg
#
# 2. Restart Klipper firmware: FIRMWARE_RESTART
#
# 3. Test with: HEAT_SOAK BED_TEMP=60 SOAK_TIME=120
# (This runs a short 2-minute test at 60°C)
#
# 4. Optional: Configure a beeper for audio feedback
# [output_pin beeper]
# pin: YOUR_BEEPER_PIN
# pwm: True
# cycle_time: 0.0005
#
# [gcode_macro BEEP]
# gcode:
# SET_PIN PIN=beeper VALUE=0.8
# G4 P100
# SET_PIN PIN=beeper VALUE=0
#
# ============================================================================
# TROUBLESHOOTING
# ============================================================================
#
# Problem: Macro executes instantly without waiting
# Solution: Your Klipper has G4 timing issues. This macro is designed to
# work around this with 1-second delay loops.
#
# Problem: "Unknown command BEEP"
# Solution: Either configure a beeper (see above) or remove the BEEP
# commands from the completion section.
#
# Problem: Macro stops with temperature error
# Solution: Check your bed temperature limits and ensure your heated bed
# can safely reach the target temperature.
#
# Problem: Fan doesn't turn on
# Solution: Verify your printer has a part cooling fan configured as [fan]
# in your Klipper configuration.
#
# ============================================================================
# TECHNICAL NOTES
# ============================================================================
#
# - This macro uses loops of 1-second G4 P1000 delays instead of longer
# single delays to work around timing issues in some Klipper configurations
#
# - The toolhead movement pattern creates gentle air circulation without
# causing mechanical stress or noise
#
# - Parameters are validated to prevent unsafe operation
#
# - The macro is designed to be safe to interrupt with M112 emergency stop
#
# - Fan speed uses the standard 0-255 range (PWM values)
#
# ============================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment