Skip to content

Commit f6909b7

Browse files
committed
✨ Chameleon3D Filament Changer
1 parent b9f0c68 commit f6909b7

File tree

11 files changed

+451
-7
lines changed

11 files changed

+451
-7
lines changed

Marlin/Configuration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@
404404
* PRUSA_MMU3 : Průša MMU3 (Requires MK3S extruder with motion sensor and MMU firmware version 3.x.x, EXTRUDERS = 5)
405405
* EXTENDABLE_EMU_MMU2 : MMU with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
406406
* EXTENDABLE_EMU_MMU2S : MMUS with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
407+
* CHAMELEON : Chameleon with up to 4 switchable filaments
407408
*
408409
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
409410
* See additional options in Configuration_adv.h.

Marlin/Configuration_adv.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4688,6 +4688,37 @@
46884688

46894689
#endif // HAS_PRUSA_MMU2 || HAS_PRUSA_MMU3
46904690

4691+
#if HAS_CHAMELEON
4692+
4693+
#define CHAMELEON_BUTTON1_X X_MAX_POS // Button 1 depressed position
4694+
#define CHAMELEON_BUTTON2_X X_MIN_POS // Button 2 depressed position (Used for EXTRUDERS > 2)
4695+
//#define CHAMELEON_TOOLCHANGE_Y Y_CENTER // A standard Y position for all tool-changes
4696+
//#define CHAMELEON_TOOLCHANGE_Z Z_MAX_POS // Enable and adjust if the switch is top-mounted
4697+
4698+
// Design the ramming sequence to first retract out of the hotend,
4699+
// then do blob elimination at the tip, then retract all the way
4700+
// back out of the feeder splitter.
4701+
#define CHAMELEON_RAMMING_SEQUENCE \
4702+
{ -10, 10000 }, /* < fast (shape) */ \
4703+
{ -40, 600 }, /* < slow (cool) */ \
4704+
{ +50, 10000 }, /* > fast (shape) */ \
4705+
{ -10, 10000 }, /* < fast (shape) */ \
4706+
{ -40, 600 }, /* < slow (cool) */ \
4707+
{ +51, 10000 }, /* > fast (unblob) */ \
4708+
{ -11, 10000 }, /* < fast (shape) */ \
4709+
{ +11, 10000 }, /* > fast (unblob) */ \
4710+
{ -11, 10000 }, /* < fast (shape) */ \
4711+
{ +11, 10000 }, /* > fast (unblob) */ \
4712+
{ -11, 10000 }, /* < fast (shape) */ \
4713+
{ -40, 100 }, /* < slow (cool) */ \
4714+
{ -110, 10000 }, /* < fast (shape) */ \
4715+
{ +40, 1000 }, /* > fast (shape) */ \
4716+
{ -40, 1000 }, /* < fast (shape) */ \
4717+
{ +40, 1000 }, /* > fast (shape) */ \
4718+
{ -130, 5000 } /* < fast (unload) */
4719+
4720+
#endif // HAS_CHAMELEON
4721+
46914722
/**
46924723
* Advanced Print Counter settings
46934724
* @section stats
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**
2+
* Marlin 3D Printer Firmware
3+
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4+
*
5+
* Based on Sprinter and grbl.
6+
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
23+
#include "../../inc/MarlinConfig.h"
24+
25+
#if HAS_CHAMELEON
26+
27+
#include "chameleon.h"
28+
//#include "../../MarlinCore.h"
29+
#include "../../module/planner.h"
30+
#include "../../module/stepper.h"
31+
#include "../../lcd/marlinui.h"
32+
33+
//#define DEBUG_OUT ENABLED(DEBUG_CHAMELEON)
34+
#include "../../core/debug_out.h"
35+
36+
Chameleon chameleon;
37+
38+
struct E_Step {
39+
float extrude;
40+
feedRate_t feedRate;
41+
};
42+
43+
// Change tools the Chameleon 3D way
44+
void Chameleon::tool_change(const uint8_t index) {
45+
const uint8_t switches = active_extruder ^ index;
46+
if (!switches) return;
47+
48+
ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
49+
50+
#ifdef CHAMELEON_TOOLCHANGE_Y
51+
current_position.y = CHAMELEON_TOOLCHANGE_Y;
52+
#endif
53+
#ifdef CHAMELEON_TOOLCHANGE_Z
54+
NOLESS(current_position.z, CHAMELEON_TOOLCHANGE_Z);
55+
line_to_current_position(5000);
56+
#endif
57+
if (switches & 0x1) {
58+
current_position.x = CHAMELEON_BUTTON1_X + (X_CENTER > (CHAMELEON_BUTTON1_X)) ? 10 : -10;
59+
}
60+
else {
61+
#if EXTRUDERS > 2
62+
if (switches & 0x2)
63+
current_position.x = CHAMELEON_BUTTON2_X + (X_CENTER > (CHAMELEON_BUTTON2_X)) ? 10 : -10;
64+
#endif
65+
}
66+
line_to_current_position(5000);
67+
68+
static constexpr E_Step ramming_sequence[] PROGMEM = { CHAMELEON_RAMMING_SEQUENCE };
69+
execute_extruder_sequence(ramming_sequence, COUNT(ramming_sequence));
70+
71+
toggle(switches);
72+
73+
active_extruder = index;
74+
75+
ui.reset_status();
76+
}
77+
78+
// Execute a list of E moves
79+
void Chameleon::execute_extruder_sequence(const E_Step * const sequence, const uint8_t steps) {
80+
planner.synchronize();
81+
stepper.enable_extruder();
82+
83+
const E_Step *step = sequence;
84+
85+
for (uint8_t i = 0; i < steps; ++i) {
86+
const float es = pgm_read_float(&(step->extrude));
87+
const uint16_t fr_or_ms = pgm_read_float(&(step->feedRate));
88+
89+
DEBUG_ECHO_MSG("Move E", es, " @ ", fr_or_ms);
90+
91+
if (es) {
92+
current_position.e += es;
93+
line_to_current_position(MMM_TO_MMS(fr_or_ms));
94+
planner.synchronize();
95+
}
96+
else
97+
safe_delay(fr_or_ms);
98+
99+
step++;
100+
}
101+
102+
// Reset E to 0 for the new extruder tool
103+
current_position.e = 0;
104+
sync_plan_position_e();
105+
106+
stepper.disable_extruder();
107+
}
108+
109+
// Bump the switches needed to change feeders
110+
void Chameleon::toggle(const uint8_t switches) {
111+
if (switches & 0x1) {
112+
current_position.x = CHAMELEON_BUTTON1_X;
113+
line_to_current_position(2000);
114+
current_position.x += (X_CENTER > (CHAMELEON_BUTTON1_X)) ? 10 : -10;
115+
line_to_current_position(2000);
116+
}
117+
#if EXTRUDERS > 2
118+
if (switches & 0x2) {
119+
current_position.x = CHAMELEON_BUTTON2_X;
120+
line_to_current_position(2000);
121+
current_position.x += (X_CENTER > (CHAMELEON_BUTTON2_X)) ? 10 : -10;
122+
line_to_current_position(2000);
123+
}
124+
#endif
125+
planner.synchronize();
126+
}
127+
128+
#endif // HAS_CHAMELEON

Marlin/src/feature/mmu/chameleon.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Marlin 3D Printer Firmware
3+
* Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4+
*
5+
* Based on Sprinter and grbl.
6+
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
#pragma once
23+
24+
#include <stdint.h>
25+
26+
struct E_Step;
27+
28+
class Chameleon {
29+
public:
30+
Chameleon() {}
31+
static void tool_change(const uint8_t new_tool);
32+
33+
private:
34+
static void execute_extruder_sequence(const E_Step * const sequence, const uint8_t steps);
35+
static void toggle(const uint8_t switches);
36+
};
37+
38+
extern Chameleon chameleon;

Marlin/src/inc/Conditionals-1-axes.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#define _PRUSA_MMU2 2
102102
#define _PRUSA_MMU2S 3
103103
#define _PRUSA_MMU3 4
104+
#define _CHAMELEON 5
104105
#define _EXTENDABLE_EMU_MMU2 12
105106
#define _EXTENDABLE_EMU_MMU2S 13
106107
#define _EXTENDABLE_EMU_MMU3 14
@@ -115,6 +116,8 @@
115116
#define HAS_PRUSA_MMU2S 1
116117
#elif _MMU % 10 == _PRUSA_MMU3
117118
#define HAS_PRUSA_MMU3 1
119+
#elif _MMU % 10 == _CHAMELEON
120+
#define HAS_CHAMELEON 1
118121
#endif
119122
#if _MMU == _EXTENDABLE_EMU_MMU2 || _MMU == _EXTENDABLE_EMU_MMU2S
120123
#define HAS_EXTENDABLE_MMU 1
@@ -125,6 +128,7 @@
125128
#undef _PRUSA_MMU2
126129
#undef _PRUSA_MMU2S
127130
#undef _PRUSA_MMU3
131+
#undef _CHAMELEON
128132
#undef _EXTENDABLE_EMU_MMU2
129133
#undef _EXTENDABLE_EMU_MMU2S
130134
#undef _EXTENDABLE_EMU_MMU3
@@ -161,7 +165,7 @@
161165
#define E_STEPPERS EXTRUDERS
162166
#define E_MANUAL EXTRUDERS
163167

164-
#elif HAS_PRUSA_MMU2 || HAS_PRUSA_MMU3 // Průša Multi-Material Unit v2/v3
168+
#elif HAS_PRUSA_MMU2 || HAS_PRUSA_MMU3 || HAS_CHAMELEON // Multi-Material Unit
165169

166170
#define E_STEPPERS 1
167171
#define E_MANUAL 1

Marlin/src/inc/SanityCheck.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,13 +626,22 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L
626626
#endif
627627
#endif
628628

629+
#if HAS_CHAMELEON
630+
#if EXTRUDERS > 32
631+
#undef SINGLENOZZLE
632+
#error "CHAMELEON only supports up to 32 EXTRUDERS. Please update your Configuration."
633+
#endif
634+
#endif
635+
629636
/**
630637
* Options only for EXTRUDERS > 1
631638
*/
632639
#if HAS_MULTI_EXTRUDER
633640

634641
#ifndef MAX_EXTRUDERS
635-
#if HAS_EXTENDABLE_MMU
642+
#if HAS_CHAMELEON
643+
#define MAX_EXTRUDERS 32
644+
#elif HAS_EXTENDABLE_MMU
636645
#define MAX_EXTRUDERS 15
637646
#else
638647
#define MAX_EXTRUDERS 8

Marlin/src/module/stepper/indirection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,12 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
668668
#define FWD_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? HIGH : LOW ); }while(0)
669669
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? LOW : HIGH); }while(0)
670670

671+
#elif ENABLED(CHAMELEON) // One multiplexed stepper driver, reversed on T2/T3, T6/T7, T10/T11, etc.
672+
673+
#define E_STEP_WRITE(E,V) E0_STEP_WRITE(V)
674+
#define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 1) ? HIGH : LOW ); }while(0)
675+
#define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 1) ? LOW : HIGH); }while(0)
676+
671677
#elif E_STEPPERS > 1
672678

673679
#if E_STEPPERS > 7

Marlin/src/module/tool_change.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
#include "../feature/mmu/mmu2.h"
8383
#elif HAS_PRUSA_MMU1
8484
#include "../feature/mmu/mmu.h"
85+
#elif HAS_CHAMELEON
86+
#include "../feature/mmu/chameleon.h"
8587
#endif
8688

8789
#if HAS_MARLINUI_MENU
@@ -1130,6 +1132,12 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) {
11301132

11311133
mmu3.tool_change(new_tool);
11321134

1135+
#elif HAS_CHAMELEON
1136+
1137+
UNUSED(no_move);
1138+
1139+
chameleon.tool_change(new_tool);
1140+
11331141
#elif HAS_PRUSA_MMU2
11341142

11351143
UNUSED(no_move);

buildroot/tests/mega2560

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,20 @@ exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 5 | RRDFGSC | UBL | LIN_ADVANCE ..."
4040
# Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language
4141
#
4242
use_example_configs AnimationExample
43-
opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO LCD_LANGUAGE jp_kana DEFAULT_EJERK 10 \
44-
EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 5 TEMP_SENSOR_3 20 TEMP_SENSOR_4 1000 TEMP_SENSOR_BED 1
43+
opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO \
44+
EXTRUDERS 8 TEMP_SENSOR_BED 1 MMU_MODEL CHAMELEON DEFAULT_EJERK 10 LCD_LANGUAGE jp_kana
4545
opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER LIGHTWEIGHT_UI SHOW_CUSTOM_BOOTSCREEN BOOT_MARLIN_LOGO_SMALL \
4646
SET_PROGRESS_MANUALLY SET_PROGRESS_PERCENT PRINT_PROGRESS_SHOW_DECIMALS SHOW_REMAINING_TIME STATUS_MESSAGE_SCROLLING SCROLL_LONG_FILENAMES \
4747
SDSUPPORT LONG_FILENAME_WRITE_SUPPORT SDCARD_SORT_ALPHA NO_SD_AUTOSTART USB_FLASH_DRIVE_SUPPORT CANCEL_OBJECTS \
4848
Z_PROBE_SLED AUTO_BED_LEVELING_UBL UBL_HILBERT_CURVE UBL_TILT_ON_MESH_POINTS UBL_TILT_ON_MESH_POINTS_3POINT \
4949
RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT \
5050
EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_MENU_MAIN \
51-
MULTI_NOZZLE_DUPLICATION CLASSIC_JERK LIN_ADVANCE QUICK_HOME \
51+
NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE CLASSIC_JERK LIN_ADVANCE QUICK_HOME \
5252
NANODLP_Z_SYNC I2C_POSITION_ENCODERS M114_DETAIL \
5353
SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \
54-
BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING BABYSTEP_HOTEND_Z_OFFSET BABYSTEP_DISPLAY_TOTAL
54+
BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING BABYSTEP_DISPLAY_TOTAL
5555
opt_disable SEGMENT_LEVELED_MOVES
56-
exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 5 | RRDFGSC | UBL | LIN_ADVANCE | Sled Probe | Skew | JP-Kana | Babystep offsets ..." "$3"
56+
exec_test $1 $2 "Azteeg X3 Pro | Chameleon (x8) | RRDFGSC | UBL | LIN_ADVANCE | Sled Probe | Skew | JP-Kana | Babystep offsets ..." "$3"
5757

5858
#
5959
# 4 runout sensors with distinct states

0 commit comments

Comments
 (0)