Files
klipper-macros/macros/iHeater.cfg
T

259 lines
10 KiB
INI
Raw Normal View History

#========================================================
#=====================iHeater cfg========================
#========================================================
#=====================iHeater pins=======================
[board_pins iHeater_Aliases]
mcu: iHeater
aliases:
TH0=PA3, TH1=PA0, TH2=PB1,
HEATER=PA1, FAN=PA2,
MODE=PA4,
LED1=PA7, LED2=PA6, LED3=PA5,
USART1_TX=PA9, USART1_RX=PA10
#=====================iHeater mcu=======================
# [mcu]
# serial: /dev/serial/by-id/usb-Klipper_stm32f042x6_0C0018000D53304347373020-if00
[mcu iHeater] #second MCU
#is_non_critical: true: true # flag this as non critical
serial: /dev/serial/by-id/usb-Klipper_stm32f042x6_0C0020000E43304754393320-if00
restart_method: command
[temperature_sensor iHeater]
sensor_type: temperature_mcu
sensor_mcu: iHeater
#============================================================
#======================= iHeater CONFIG ======================
#============================================================
# Make sure to perform PID calibration for the chamber heater:
#🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
# PID_CALIBRATE HEATER=iHeater_H TARGET=70
#🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
# This is essential for accurate and stable chamber heating.
# Without PID tuning, the temperature may overshoot or take too long to stabilize!
#===========================================================
[heater_generic iHeater_H]
heater_pin: iHeater:HEATER
max_power: 1
sensor_type: NTC 100K MGB18-104F39050L32
sensor_pin: iHeater:TH0
pwm_cycle_time: 0.3
min_temp: 0
max_temp: 120
control: pid
# pid_Kp: 37.948
# pid_Ki: 2.040
# pid_Kd: 176.497
pid_Kp: 26.656
pid_Ki: 0.96
pid_Kd: 184.971
[verify_heater iHeater_H]
max_error: 240
check_gain_time: 1800
heating_gain: 1
[heater_fan chamber_heater_fan]
pin: iHeater:FAN
heater: iHeater_H
heater_temp: 50.0
fan_speed: 1.0
shutdown_speed: 0
kick_start_time: 0.5
[temperature_sensor iHeater_S]
sensor_pin: iHeater:TH1
sensor_type: NTC 100K MGB18-104F39050L32
min_temp: 0
max_temp: 140
# [temperature_sensor iHeater_Chamber_ext]
# sensor_pin: iHeater:TH2
# sensor_type: NTC 100K MGB18-104F39050L32
# min_temp: 0
# max_temp: 140
[gcode_button mode_button]
pin: iHeater:MODE
# debounce_delay: 50
press_gcode: iHEATER_OFF
# [output_pin led_1]
# pin: iHeater:LED1
# [output_pin led_2]
# pin: iHeater:LED2
# [output_pin led_3]
# pin: iHeater:LED3
#######################################################
##########################SETUP########################
#######################################################
[gcode_macro CHAMBER_VARS]
variable_chamber_target: 0 # target chamber temperature, °C
variable_start_offset: 10 # printing can start when chamber reaches (target - offset)
variable_delta_temp: 10 # delta between chamber and heater, °C
variable_min_heater_temp: 50 # minimum heater temperature (for cooling), °C
variable_max_heater_temp: 100 # maximum heater temperature, °C
variable_control_interval: 1.0 # interval for control function call, seconds
variable_air_min_delta: 0.5 # minimum difference between desired and current chamber temperature (heater temp = desired + delta_temp), °C
variable_air_max_delta: 5.0 # maximum difference between desired and current chamber temperature (heater temp = max_heater_temp), °C
gcode:
##########################MACRO########################
[gcode_macro M141]
#rename_existing: M141.1
gcode:
# Get desired chamber temperature:
# - if parameter S is passed, use it
# - otherwise use chamber_target from CHAMBER_VARS
{% set chamber_target = params.S|default(printer["gcode_macro CHAMBER_VARS"].chamber_target)|int %}
# Get delta temperature:
# - if parameter D is passed, use it
# - otherwise use delta_temp from CHAMBER_VARS
{% set delta_temp = params.D|default(printer["gcode_macro CHAMBER_VARS"].delta_temp)|int %}
# Get maximum heater temperature:
# - if parameter H is passed, use it
# - otherwise use max_heater_temp from CHAMBER_VARS
{% set max_heater_temp = params.H|default(printer["gcode_macro CHAMBER_VARS"].max_heater_temp)|int %}
# Get interval for control function call
{% set control_interval = printer["gcode_macro CHAMBER_VARS"].control_interval|float %}
RESPOND prefix="M141" msg="S{chamber_target} D{delta_temp} H{max_heater_temp}"
# Save parameters to CHAMBER_VARS for delayed_gcode
SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=chamber_target VALUE={chamber_target}
SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=delta_temp VALUE={delta_temp}
SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=max_heater_temp VALUE={max_heater_temp}
# Initial calculation
iHEATER_CONTROL
# Start temperature control macro
UPDATE_DELAYED_GCODE ID=_iHEATER_CONTROL DURATION={control_interval}
[gcode_macro M191]
#rename_existing: M191.1
gcode:
# Get desired chamber temperature:
# - if parameter S is passed, use it
# - otherwise use chamber_target from CHAMBER_VARS
{% set chamber_target = params.S|default(printer["gcode_macro CHAMBER_VARS"].chamber_target)|int %}
# Get delta temperature:
# - if parameter D is passed, use it
# - otherwise use delta_temp from CHAMBER_VARS
{% set delta_temp = params.D|default(printer["gcode_macro CHAMBER_VARS"].delta_temp)|int %}
# Get maximum heater temperature:
# - if parameter H is passed, use it
# - otherwise use max_heater_temp from CHAMBER_VARS
{% set max_heater_temp = params.H|default(printer["gcode_macro CHAMBER_VARS"].max_heater_temp)|int %}
# Get minimum chamber temperature for print start:
# - if parameter W is passed, use it
# - otherwise use start_offset from CHAMBER_VARS
{% set start_offset = params.W|default(printer["gcode_macro CHAMBER_VARS"].start_offset)|int %}
RESPOND prefix="M191" msg="S{chamber_target} D{delta_temp} H{max_heater_temp} W{start_offset}"
M141 S{chamber_target} D{delta_temp} H{max_heater_temp}
# Save parameter to CHAMBER_VARS
SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=start_offset VALUE={start_offset}
# Wait until chamber reaches the target temperature
TEMPERATURE_WAIT SENSOR="temperature_sensor iHeater_S" MINIMUM={chamber_target - start_offset}
RESPOND prefix="M191" msg="Chamber reached {chamber_target - start_offset}°C"
[gcode_macro iHEATER_ON]
description: Alternative to M141 & M191 with alternative parameter names
gcode:
{% set s = params.CHAMBER_TEMP|default(printer["gcode_macro CHAMBER_VARS"].chamber_target)|int %}
{% set d = params.DELTA|default(printer["gcode_macro CHAMBER_VARS"].delta_temp)|int %}
{% set h = params.HEATER_MAX|default(printer["gcode_macro CHAMBER_VARS"].max_heater_temp)|int %}
{% set w = params.CHAMBER_AWAIT_TEMP|default(printer["gcode_macro CHAMBER_VARS"].start_offset)|int %}
{% if w > 0 %}
# If w is greater than 0, use M191 with wait for minimum temperature
M191 S{s} D{d} H{h} W{s - w}
{% else %}
# Otherwise use M141 without waiting
M141 S{s} D{d} H{h}
{% endif %}
[gcode_macro iHEATER_OFF]
gcode:
SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=chamber_target VALUE=0
# SET_GCODE_VARIABLE MACRO=CHAMBER_VARS VARIABLE=start_offset VALUE=0
UPDATE_DELAYED_GCODE ID=_iHEATER_CONTROL DURATION=1
RESPOND prefix="iHeater_off" msg="Heating disabled."
[gcode_macro iHEATER_CONTROL]
gcode:
# Target chamber temperature
{% set target_chamber_temp = printer["gcode_macro CHAMBER_VARS"].chamber_target|float %}
# Delta - how much the heater temp exceeds chamber temp
{% set delta_temp = printer["gcode_macro CHAMBER_VARS"].delta_temp|float %}
# Minimum heater temperature
{% set min_heater_temp = printer["gcode_macro CHAMBER_VARS"].min_heater_temp|float %}
# Maximum heater temperature
{% set max_heater_temp = printer["gcode_macro CHAMBER_VARS"].max_heater_temp|float %}
# Current heater temperature
{% set heater_temp = printer["heater_generic iHeater_H"].temperature|float %}
# Current chamber air temperature (from sensor)
{% set chamber_temp = printer["temperature_sensor iHeater_S"].temperature|float %}
# Control function call interval
{% set control_interval = printer["gcode_macro CHAMBER_VARS"].control_interval|float %}
# Minimum difference between desired and current chamber temperature
{% set air_min_delta = printer["gcode_macro CHAMBER_VARS"].air_min_delta|float %}
# Maximum difference between desired and current chamber temperature
{% set air_max_delta = printer["gcode_macro CHAMBER_VARS"].air_max_delta|float %}
# Variable to set target heater temperature
{% set target_heater_temp = 0.0 %}
# RESPOND prefix="iHeater_control" msg="Heater control..."
{% if target_chamber_temp > 0 %}
# Heating is active
{% set temp_diff = target_chamber_temp - chamber_temp %}
# MapToRange
{% set value = temp_diff %}
{% set inputLowerBound = air_min_delta %}
{% set inputUpperBound = air_max_delta %}
{% set outputLowerBound = delta_temp %}
{% set outputUpperBound = [delta_temp, max_heater_temp - target_chamber_temp]|max %}
{% set slope = (outputUpperBound - outputLowerBound) / (inputUpperBound - inputLowerBound) %}
{% set clamped = ([inputLowerBound, value, inputUpperBound]|sort)[1] %}
{% set adjustment = outputLowerBound + slope * (clamped - inputLowerBound) %}
{% set target_heater_temp = (target_chamber_temp + adjustment)|round(2) %}
{% elif heater_temp > min_heater_temp %}
# Heating is off, but heater hasn't cooled down yet
RESPOND prefix="iHeater_control" msg="Cooling down the heater..."
{% else %}
# Heater cooled down - end macro
RESPOND prefix="iHeater_control" msg="Heater cooldown complete."
{% set control_interval = 0.0 %}
{% endif %}
SET_HEATER_TEMPERATURE HEATER=iHeater_H TARGET={target_heater_temp}
UPDATE_DELAYED_GCODE ID=_iHEATER_CONTROL DURATION={control_interval}
[delayed_gcode _iHEATER_CONTROL]
gcode:
iHEATER_CONTROL