-
Notifications
You must be signed in to change notification settings - Fork 225
Environment Manager
- Hardware Config
- Parameter Config
- MMU_HEATER Command
- Single-Heater Mode Operation
- Per-Gate Heater Mode Operation
- Venting Macro
- Spool Rotation
- Printer Variables
- Troubleshooting
Happy Hare includes an MMU Environment Manager that can control one heater (shared enclosure) or multiple heaters (one per gate) and provides a managed filament drying cycle. Drying can terminate based on a timer or (if the sensor supports it) humidity goal. During drying the manager can optionally call a venting macro and, if an eSpooler is fitted, periodically rotate spools -- converting your MMU into a formidable filament dryer!
Warning
This functionality provides the ability to keep heaters powered for a long period of time. Always exercise caution when using to ensure no malfunction occurs - you don't want your MMU to melt or anything worse!
Two setups are supported:
-
Single-heater / shared enclosure
A single heater warms a shared chamber; a single environment sensor provides temperature (and optionally humidity). -
Per-gate heaters (e.g. the modular EMU MMU design)
Each gate has its own heater and environment sensor. A basic “power management” queue limits the number of simultaneously active heaters.
Configure a heater and an environment sensor:
# Full name of environment sensor object for MMU filament storage (displays temp and humidity in UI).
# Leave empty if sensor is not fitted. Polls for "temperature" and "humidity"
# E.g. If you have a section like this: [temperature_sensor MMU_enclosure]
# Set: environment_sensor: temperature_sensor MMU_enclosure
environment_sensor: temperature_sensor mmu_environment
# Full name of filament heater object. Leave empty if heater is not fitted
# E.g. If you have a section like this: [heater_generic MMU_heater]
# Set: filament_heater: heater_generic MMU_heater
filament_heater: heater_generic mmu_heaterConfigure a list of heaters and sensors, one per gate, plus a concurrency limit:
# PER-GATE heaters and environment sensors. Some modular MMU designs have per-gate control (e.g. EMU). For this type of MMU, leave
# 'environment_sensor' and 'filament_heater' empty and define a list of heaters and sensors here. Note the length of the list must
# match the number of gates. Leave this settings empty if defining a single sensor/heater.
environment_sensors: # Comma separated list of full environment sensor object names
filament_heaters: # Comma separated list of full heater object names
max_concurrent_heaters: 1 # Limit the number of simultaneously active heaters (power/PSU protection)Important
Configure only a single heater/sensor or per-gate heater/sensor. Configuring both will result in an config error.
The manager uses the following parameters. Defaults are generally a good starting point.
# Heater / Environment Management ------------------------------------------------------------------------------------
# ██╗ ██╗███████╗ █████╗ ████████╗███████╗██████╗
# ██║ ██║██╔════╝██╔══██╗╚══██╔══╝██╔════╝██╔══██╗
# ███████║█████╗ ███████║ ██║ █████╗ ██████╔╝
# ██╔══██║██╔══╝ ██╔══██║ ██║ ██╔══╝ ██╔══██╗
# ██║ ██║███████╗██║ ██║ ██║ ███████╗██║ ██║
# ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
#
heater_max_temp: 70 # Absolute max heater setting to protect the MMU enclosure construction (adjust to match material)
heater_default_dry_temp: 45 # Default drying temperature if filament type is not matched in drying_data
heater_default_dry_time: 300 # Default drying cycle time in minutes
heater_default_humidity: 25 # Default humidity % goal. Drying will terminate if this value is reached
heater_vent_macro: _MMU_VENT # Name of macro to periodicaly call during drying cycle
heater_vent_interval: 0 # Interval in minutes to call heater_vent_macro during drying cycle, 0=disable venting
heater_rotate_interval: 5 # Interval in minutes to rotate filament (requires eSpooler and filament end attached to spool)
# Drying data for MMU_HEATER DRY=1 command in form (material type is case insensitive):
# 'filament_type': (temp, drying_time_mins)
#
# (Careful with formatting of this line - reformatting will break upgrade logic)
#
drying_data: { 'pla': (45, 300), 'pla+': (55, 300), 'petg': (60, 300), 'tpu': (55, 300), 'abs': (70, 300), 'abs+': (75, 300), 'asa': (65, 300), 'nylon': (75, 600), 'pc': (75, 600), 'pva': (75, 600), 'hips': (75, 600) }Note
- Venting and spool rotation are only active during a drying cycle and not just with heater activated.
- Venting requires the user to complete the venting macro based on the supplied template
- Rotation is only available if eSpooler is fitted to MMU
The drying_data table defines recommended temperature and time per material. Keys are treated case-insensitively (internally normalized to uppercase). This table gives the drying functionality some power but also safeguards: Loaded filaments types are compared to this table and the optimum temperature and duration are calculated. In most MMU designs with shared enclosure this will pick the lowest common denominator but in advanced module designs like the EMU, per-gate heating can be different. Read more about this later.
drying_data: "{'PLA': (45, 240), 'PETG': (55, 300), 'NYLON': (65, 480)}"- Values are
(temperature_C, time_minutes) - Missing materials fall back to
heater_default_dry_tempandheater_default_dry_time
To print the configured table at runtime:
MMU_HEATER DRYING_DATA=1You are free to extend the supplied default table if you use other filament types.
The MMU_HEATER command controls heater(s) and manages drying cycles.
Execute without arguments to display the current status.
> MMU_HEATER HELP=1
MMU_HEATER: Control MMU heater(s) and filament drying cycle
└ STOP = [0|1] Turn off heater and drying cycle
└ DRYING_DATA = [0|1] Dump configured drying data for filament types
└ DRY = [0|1] Disable/enable filament heater for filament drying cycle
└ TIMER = #(mins) Force drying time
└ TEMP = #(degrees) Force temperature
└ HUMIDITY = % Terminate drying when humidty goal is reached
└ GATES = x,y Gates to control ONLY IF MMU has per-gate heaters/dryers
└ ROTATE = [0|1] Rotate spool (requires eSpooler and explicit GATES)
└ ROTATE_INTERVAL = #(mins) How often to rotate spools when drying (requires eSpooler)
└ VENT_INTERVAL = #(mins) How often to call 'vent' macro in drying cycle
└ (no parameters for status report)
More details:
-
STOP – Stop drying and turn off heater(s). In per-gate mode,
GATES=cancels only those gates. - DRY – Start a drying cycle. Most other parameters are to qualify this
- TEMP – Override automatic temperature for a cycle, or set raw heater temperature (no managed cycle).
- TIMER – Override automatic filament drying time.
-
HUMIDITY – End the drying cycle early once humidity <= target (overrides
heater_default_humidity) -
GATES – In per-gate mode selects which gates to control (dry or stop). Required for
ROTATE=1. -
ROTATE – Enable periodic eSpooler rotation during drying (if eSpooler is fitted).
GATESmust be specified. -
ROTATE_INTERVAL – Override the configured
heater_rotate_intervaltimer for this drying cycle -
VENT_INTERVAL – Override the configured
heater_vent_intervaltimer for this drying cycle.
Calling MMU_HEATER with no parameters prints a status report (drying state, temps/humidity, per-gate state in per-gate mode, venting/rotation state when applicable). E.g.
> MMU_HEATER
Not in drying cycle and heater is off
or if in single heater drying cycle:
> MMU_HEATER
MMU is in filament drying cycle:
Drying filaments in gates: 1,2,6,7
Cycle time: 4 hours (remaining: 3 hours 46 minutes)
Target humidity: 25.5% (current: 63.6%)
Drying temp: 55.0°C (current: 48.3°C)
Venting operational (running macro _MMU_VENT every 15 minutes, next in 11 minutes)
Spool rotation enabled (every 5 minutes, next in <1 minute)
with per-gate heaters, additional status will be reported, for example:
...
Per-gate dryer mode (max concurrent heaters: 3). Humidity target 25.5%
Gate 1: (timer complete, final humidity: 22.3%)
Gate 2: Drying ABS 27.3°C (target 65.0°C), humidity 62.9%, 1 hour 1 minute remaining
Gate 5: Drying PLA 27.3°C (target 45.0°C), humidity 63.1%, 1 hour 1 minute remaining
Gate 6: Drying PETG 27.3°C (target 55.0°C), humidity 63.6%, 13 minutes remaining
Gate 7: (queued waiting for heater slot, PLA target 45.0°C)
Gate 8: (queued waiting for heater slot, ABS target 65.0°C)
Single-heater mode is used when filament_heater + environment_sensor are configured (and per-gate lists are not). This is the most common setup for MMU designs with a shared heated enclosure.
MMU_HEATER TEMP=50- This simply sets the heater temperature and if in a drying cycle it adjusts that currently in use.
- CAUTION: If not in a drying cycle there is no automatic off, so use
MMU_HEATER TEMP=0,MMU_HEATER STOP=0or other heater controls to switch off.
MMU_HEATER DRY=1- If
TEMPis not specified, the manager selects a recommended temperature/time fromdrying_databased on current gate materials.- This is the lowest safe temp across selected materials, and longest time across selected materials in gates that are not empty.
- If a gate is empty then filament data is ignored
- If a gate doesn't have a filament type defined in the gate map then the default
heater_default_dry_tempandheater_default_dry_timewill be assumed.
Override defaults:
MMU_HEATER DRY=1 TEMP=50 TIMER=240 HUMIDITY=12MMU_HEATER STOP=1If the configured environment sensor supports humidity, drying will end early once humidity <= HUMIDITY.
Per-gate mode is used when the MMU has a heater and senser per gate with separate spool enclosures. In this case both filament_heaters and environment_sensors lists must be configured in mmu_hardware.cfg.
MMU_HEATER DRY=1 GATES=0,2,3- Each gate uses its own recommended temperature/time from
drying_dataunless overridden. - If
TEMPis specified, it overrides temperatures for all selected gates. - Each gate monitors humidity from its own environment sensor (if available).
- If
GATESparameters is not supplied, the manager defaults to all non-empty gates.
Note
- When using
ROTATE=1, you must explicitly supplyGATES=because spool rotation is only possible if the filament tip is removed from the MMU (MMU_EJECT) and secured to the spool. The gate will therefore be marked empty and hence the need for theGATESspecifcation.
If max_concurrent_heaters is less than the number of gates being dried, the manager:
- Starts drying on up to
max_concurrent_heatersgates - Queues remaining gates
- Starts the next queued gate when an active gate completes
This means the total wall-clock time may be longer than a single-gate timer.
To cancel only specific gates during an active per-gate cycle:
MMU_HEATER STOP=1 GATES=1,3- Active gates: heater turned off immediately and marked done
- Queued gates: removed from queue and marked done
If all selected gates are completed/cancelled, the overall cycle ends automatically.
To directly set per-gate heater targets (not a managed drying cycle):
MMU_HEATER TEMP=45 GATES=0,1Behavior when a managed cycle is running:
- If a gate is queued, only the target is updated; the heater is not turned on until the gate becomes active.
- If a gate is active, the heater is updated immediately.
- If a gate is not part of the current cycle, it is set immediately.
Venting is optional and runs only during a drying cycle. The purpose is to allow warm humid air to be flushed from the enclosure thus decreasing drying time. Many MMU's have a passive vent system but some employ a servo actuated vent and perhaps even an extraction fan. The use of a user defined macro allows complete flexibility for your particular setup.
The vent macro should both open and close the vent, however it is only called once. It is not recommended to wait (M400) inside of the macro but instead queue a delayed vent close macro. The supplied example _MMU_VENT is a great template and demonstrates how this can be accomplished.
Venting functional is enabled by setting:
heater_vent_macroheater_vent_interval > 0
Or override for a single run:
MMU_HEATER DRY=1 VENT_INTERVAL=10Behavior:
- Single-heater mode: macro runs with no args
- Per-gate mode: macro runs with
GATES=<list of currently active gates>
You can find this skeleton macro in config/mmu/base/mmu_heater_vent.cfg. It demonstrates how to use delayed_gcode to close the vent after some time period.
[gcode_macro _MMU_VENT]
description: Simple reference MMU enclosure venting control
gcode:
{% set gates = (params.GATES | default('')).split(',') | map('trim') | list %}
{% if gates == [''] %}
MMU_LOG MSG="Opening MMU vent..."
# Add logic to operate servo to open vent here, perhaps also turn on/up extraction fan
{% else %}
MMU_LOG MSG="Opening MMU vent to dry filaments in gates: {", ".join(gates)}..."
{% for gate in range(gate) %}
# Open vent servo_{gate}
{% endfor %}
{% endif %}
# Close the vent after 10 seconds
UPDATE_DELAYED_GCODE ID=_MMU_VENT_CLOSE DURATION=10
[delayed_gcode _MMU_VENT_CLOSE]
gcode:
MMU_LOG MSG="Closing MMU vent..."
# Add logic to operate servo to close vent here, perhaps also turn off/down extraction fan
The manager can optionally rotate spools during drying if an eSpooler is fitted and the cycle is started with ROTATE=1.
MMU_HEATER DRY=1 ROTATE=1 GATES=1,3Note:
-
GATES=must be explicitly provided whenROTATE=1 - On start, the manager warns if any specified gates are not EMPTY (drying still proceeds). This is necessary because a loaded gate cannot rotate!
- Every
heater_rotate_intervalminutes, the manager:- re-checks the current gate status
- rotates only gates that are EMPTY at that moment (so you can unload a gate and secure filament end whist drying is active)
- spool rotation is a short burst in the rewind direction. The speed and duration are exactly the same as the assist burst but in the opposite direction and can be defined with these parameters in
mmu_parameters.cfg(which default to their "assist" siblings:
espooler_rotate_burst_power: 80
espooler_rotate_burst_duration: 0.5Important
Filament must be removed from the MMU inlet and fastened to the spool. Rotation is only possible when the gate is EMPTY!
The environment manager exposes the follow printer variable for UI / clients:
drying_state : [{string}] List of state for each gate (active|queued|complete|cancelled|'')- The environment sensor may not support humidity, or humidity chip is not supported.
- Drying will still run using time, but humidity early-termination will not occur.
-
heater_vent_macrois blank or not available, orheater_vent_intervalis0. - If venting is enabled, check console and
mmu.logfor macro errors.
- Gates may be queued due to
max_concurrent_heaters. - Total time = sum of per-gate timers when fully serialized by the queue.
- eSpooler not fitted or enabled, or
-
ROTATE=1not specified, or - gates were not EMPTY at rotation tick (rotation can only occure on "EMPTY" gates with filament secured to the spool).
(\_/)
( *,*)
(")_(") Happy Hare ReadyCopyright (C) 2022-2026 Paul Morgan
1. Introduction
2. Installation
3. Essential Configuration
5. Operation
-- YOUR MMU IS READY TO PLAY WITH --
6. Slicer-MMU Setup
-- NOW YOU ARE READY TO PRINT! --
7. Tuning
8. Optional Feature Setup
9. Advanced Configuration
10. Advanced Concepts
- State Persistence
- Statistics and Counters
- Tool and Gate Maps
- Filament Bypass
- Runout/Clog Detection
- Consumption Counters
- Synchronized Gear/Extruder
11. Quick References
12. Troubleshooting
13. FAQ
14. MCU Board Reference 🆕
15. Change Log
Happy Hare Discord
Hardware Config
Drying Data Setup