voronklipperconfig/mmu/addons/dc_espooler.cfg
2025-03-20 15:01:04 +00:00

202 lines
8 KiB
INI

####################################
# Variables for the eSpooler macros
#
# Configure these for your setup.
#
[gcode_macro _MMU_ESPOOLER_VARS]
# Prefix of name of the `output_pin` for the eSpooler.
# The `output_pin` name must follow the pattern {prefix}_rwd_{gate}
# and {prefix}_en_{gate}. By default we prefix it with an underscore
# to prevent them from being shown in UI applications (like mainsail).
#
variable_pin_prefix: '_mmu_dc_espooler'
# Default max number of seconds for eSpooler to run
# Note: Each time any eSpooler **starts** it will restart the timeout
#
variable_default_timeout: 60
# The step speed where you want to max out the eSpooler to run at full speed.
#
variable_max_step_speed: 200
# Minimum distance of a move required to activate the eSpooler
# The lowest valid value for this is 50 because eSpooler macros
# will not even be considered if the distance is less than 50.
#
variable_min_distance: 200
# Adjusts the speed conversion ratio
# For the following examples, let's assume max_step_speed = 50.
# And remember actual eSpooler speed values are between 0.0 (off) and 1.0 (full speed) (inclusive)
#
# The formula looks like this:
# ({step_speed} / {max_step_speed}) ^ {step_speed_exponent}
#
# With step_speed_exponent of 1 would have a linear ratio:
# If I am running with a step speed of 50mm/s, the eSpooler would run at full speed (1.0)
# Calculated via (50/50)^1
# If I am running with a step speed of 25mm/s, the eSpooler would run at half speed (0.5)
# Calculated via (25/50)^1
#
# With step_speed_exponent of 0.2 would have a linear ratio:
# If I am running with a step speed of 50mm/s, the eSpooler would run at full speed (1.0)
# Calculated via (50/50)^0.2
# If I am running with a step speed of 25mm/s, the eSpooler would run at half speed (0.87)
# Calculated via (25/50)^0.2
#
variable_step_speed_exponent: 0.5
# Internal variable for tracking the gates with eSpoolers
variable_espooler_gates: ''
gcode: # Leave empty
###########################################################################
# Include DC motor pin definitions
#
# This should be after the eSpooler vars macro to ensure the users
# custom vars override our default ones.
#
[include dc_espooler_hw.cfg]
###########################################################################
# Macro to actuate the correct DC motor for the gate being unloaded
#
# Easiest integration is to set this in mmu_parameters.cfg:
#
# eSpooler_start_macro: MMU_ESPOOLER_START
#
[gcode_macro MMU_ESPOOLER_START]
gcode:
_MMU_ESPOOLER_CTL {rawparams}
# Param hints UI
{% set dummy = None if True else "
{% set d = params.GATE|default(current_gate)|int %}
{% set d = params.SCALE|default(cfg_scale)|float %}
{% set d = params.TIMEOUT|default(default_timeout)|float %}
" %} # End param hints for UI
###########################################################################
# Macro to stop the DC eSpooler motor
#
# Easiest integration is to set this in mmu_macro_vars.cfg:
#
# eSpooler_stop_macro: MMU_ESPOOLER_STOP
#
[gcode_macro MMU_ESPOOLER_STOP]
gcode:
_MMU_ESPOOLER_CTL {rawparams} SPEED={0}
# Param hints UI
{% set dummy = None if True else "
{% set d = params.GATE|default(current_gate)|int %}
" %} # End param hints for UI
###########################################################################
# Macro to control the DC eSpooler motor
#
# Used by both the start and stop eSpooler macros
#
[gcode_macro _MMU_ESPOOLER_CTL]
gcode:
{% set vars = printer["gcode_macro _MMU_ESPOOLER_VARS"] %}
{% set current_gate = printer['mmu'].gate %}
{% set gate = params.GATE|default(current_gate)|int %}
{% set step_speed = params.STEP_SPEED|default(-1)|float %}
{% set expected_distance = params.MAX_DISTANCE|default(-1)|float %}
{% set homing_move = params.HOMING_MOVE|default(0)|int %}
{% set speed = params.SPEED|default(-1)|float %}
{% set pin_prefix = vars.pin_prefix %}
{% set pin = ('%s_rwd_%d' % (pin_prefix, gate)) if printer['output_pin %s_rwd_%d' % (pin_prefix, gate)] else None %}
{% set en_pin = ('%s_en_%d' % (pin_prefix, gate)) if printer['output_pin %s_en_%d' % (pin_prefix, gate)] else None %}
{% set pin_cfg = ('output_pin %s' % pin) if pin else None %}
{% set pwm = (printer.configfile.settings[pin_cfg].scale) if pin_cfg else False %}
{% set default_timeout = vars.default_timeout %}
{% set timeout = params.TIMEOUT|default(default_timeout)|float %}
# Convert speed
{% if speed < 0 and step_speed >= 0 %}
# determine speed from step speed
{% if not pwm %}
# TODO: something special for long slow (tbd) moves?
# delayed start so it runs after the stepper has run for a little bit?
# or just don't run on long slow moves?
{% set speed = 1 %}
{% elif step_speed > vars.max_step_speed %}
{% set speed = 1 %}
{% else %}
{% set speed = (step_speed / vars.max_step_speed) ** vars.step_speed_exponent %}
{% endif %}
{% elif speed < 0 %}
{% set speed = 1 %}
{% endif %}
{% if gate < 0 %}
RESPOND TYPE=error MSG="No active gate. Cannot start espooler."
{% elif not pin %}
RESPOND TYPE=error MSG="{pin_cfg} does not exist. Cannot start espooler."
{% elif expected_distance >= 0 and expected_distance < vars.min_distance %}
MMU_LOG DEBUG=1 MSG="Travel distance ({expected_distance}) is shorter than the configured min distance ({vars.min_distance}). Ignoring espooler activation."
{% else %}
MMU_LOG DEBUG=1 MSG="Setting espooler {pin} to {speed}"
{% set cfg_scale = printer.configfile.settings[pin_cfg].scale|default(1)|float %}
{% set scale = params.SCALE|default(cfg_scale)|float %}
{% if en_pin and speed > 0 %}
SET_PIN PIN="{en_pin}" value="{1}"
{% endif %}
SET_PIN PIN="{pin}" value="{speed * cfg_scale * scale}"
{% if timeout > 0 and speed > 0 and printer[pin_cfg].value == 0 %}
UPDATE_DELAYED_GCODE ID=mmu_espooler_timeout DURATION={timeout}
{% elif speed == 0 %}
# Cancel delayed gcode...if all are turned off
{% set values = [] %}
{% for igate in (vars.espooler_gates) %}
{% set value = printer['output_pin %s_rwd_%d' % (pin_prefix, igate)].value %}
{% set value = 0 if (igate == gate or value == 0) else value %}
{% set d = values.append(value) %}
{% endfor %}
{% if values|sum == 0 %}
UPDATE_DELAYED_GCODE ID=mmu_espooler_timeout DURATION=0
{% endif %}
{% endif %}
{% if en_pin and speed == 0 %}
SET_PIN PIN="{en_pin}" value="{0}"
{% endif %}
{% endif %}
###########################################################################
# Delayed gcode to run on startup to identify all the eSpoolers which
# will be used after espooler timeout to ensure all eSpoolers have
# stopped.
#
[delayed_gcode mmu_espooler_startup]
initial_duration: 1.
gcode:
{% set vars = printer["gcode_macro _MMU_ESPOOLER_VARS"] %}
{% set pin_prefix = vars.pin_prefix %}
{% set pin_cfg_prefix = 'output_pin %s_rwd_' % pin_prefix %}
{% set espooler_gates = [] %}
{% for key in printer %}
{% if key.startswith(pin_cfg_prefix) %}
{% set gate = key | replace(pin_cfg_prefix, '') | int %}
{% set d = espooler_gates.append(gate | string) %}
{% endif %}
{% endfor %}
SET_GCODE_VARIABLE MACRO=_MMU_ESPOOLER_VARS VARIABLE=espooler_gates VALUE={espooler_gates|join(',')}
###########################################################################
# Delayed gcode to stop all eSpooler after timeout. This is used as a
# failsafe (unless explicitly disabled by setting a timeout of 0) to ensure
# the eSpoolers do not run indefinitely.
#
[delayed_gcode mmu_espooler_timeout]
gcode:
{% set vars = printer["gcode_macro _MMU_ESPOOLER_VARS"] %}
{% for gate in (vars.espooler_gates) %}
MMU_ESPOOLER_STOP GATE={gate}
{% endfor %}