diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 4fd27c956cc3..6de7268a4b6f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -377,6 +377,7 @@ * PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5) * EXTENDABLE_EMU_MMU2 : MMU with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware) * EXTENDABLE_EMU_MMU2S : MMUS with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware) + * CHAMELEON : Chameleon with up to 4 switchable filaments * * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails. * See additional options in Configuration_adv.h. diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 1f22c6d7a501..258b51988edc 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -4462,7 +4462,35 @@ //#define MMU2_DEBUG // Write debug info to serial output -#endif // HAS_PRUSA_MMU2 +#elif HAS_CHAMELEON + #define CHAMELEON_BUTTON1_X X_MAX_POS // Button 1 depressed position + #define CHAMELEON_BUTTON2_X X_MIN_POS // Button 2 depressed position (Used for EXTRUDERS > 2) + //#define CHAMELEON_TOOLCHANGE_Y Y_CENTER // A standard Y position for all tool-changes + //#define CHAMELEON_TOOLCHANGE_Z Z_MAX_POS // Enable and adjust if the switch is top-mounted + + // Design the ramming sequence to first retract out of the hotend, + // then do blob elimination at the tip, then retract all the way + // back out of the feeder splitter. + #define CHAMELEON_RAMMING_SEQUENCE \ + { -10, 10000 }, /* < fast (shape) */ \ + { -40, 600 }, /* < slow (cool) */ \ + { +50, 10000 }, /* > fast (shape) */ \ + { -10, 10000 }, /* < fast (shape) */ \ + { -40, 600 }, /* < slow (cool) */ \ + { +51, 10000 }, /* > fast (unblob) */ \ + { -11, 10000 }, /* < fast (shape) */ \ + { +11, 10000 }, /* > fast (unblob) */ \ + { -11, 10000 }, /* < fast (shape) */ \ + { +11, 10000 }, /* > fast (unblob) */ \ + { -11, 10000 }, /* < fast (shape) */ \ + { -40, 100 }, /* < slow (cool) */ \ + { -110, 10000 }, /* < fast (shape) */ \ + { +40, 1000 }, /* > fast (shape) */ \ + { -40, 1000 }, /* < fast (shape) */ \ + { +40, 1000 }, /* > fast (shape) */ \ + { -130, 5000 } /* < fast (unload) */ + +#endif /** * Advanced Print Counter settings diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 784002c769c4..8fcaca384f9b 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -302,6 +302,12 @@ #define GANG_N_1(N,K) _GANG_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) // Expansion of some list items +#define LIST_32(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD,EE,FF,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD,EE,FF +#define LIST_31(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD,EE,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD,EE +#define LIST_30(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,DD +#define LIST_29(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,CC +#define LIST_28(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,BB,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,TU,V,W,X,Y,Z,AA,BB +#define LIST_27(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA #define LIST_26(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z #define LIST_25(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y #define LIST_24(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,...) A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X @@ -564,6 +570,17 @@ #define INC_18 19 #define INC_19 20 #define INC_20 21 +#define INC_21 22 +#define INC_22 23 +#define INC_23 24 +#define INC_24 25 +#define INC_25 26 +#define INC_26 27 +#define INC_27 28 +#define INC_28 29 +#define INC_29 30 +#define INC_30 31 +#define INC_31 32 #define INCREMENT_(n) INC_##n #define INCREMENT(n) INCREMENT_(n) @@ -599,6 +616,23 @@ #define DEC_13 12 #define DEC_14 13 #define DEC_15 14 +#define DEC_16 15 +#define DEC_17 16 +#define DEC_18 17 +#define DEC_19 18 +#define DEC_20 19 +#define DEC_21 20 +#define DEC_22 21 +#define DEC_23 22 +#define DEC_24 23 +#define DEC_25 24 +#define DEC_26 25 +#define DEC_27 26 +#define DEC_28 27 +#define DEC_29 28 +#define DEC_30 29 +#define DEC_31 30 +#define DEC_32 31 #define DECREMENT_(n) DEC_##n #define DECREMENT(n) DECREMENT_(n) diff --git a/Marlin/src/feature/mmu/chameleon.cpp b/Marlin/src/feature/mmu/chameleon.cpp new file mode 100644 index 000000000000..a10daa0f9aa8 --- /dev/null +++ b/Marlin/src/feature/mmu/chameleon.cpp @@ -0,0 +1,128 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../../inc/MarlinConfig.h" + +#if HAS_CHAMELEON + +#include "chameleon.h" +//#include "../../MarlinCore.h" +#include "../../module/planner.h" +#include "../../module/stepper.h" +#include "../../lcd/marlinui.h" + +//#define DEBUG_OUT ENABLED(DEBUG_CHAMELEON) +#include "../../core/debug_out.h" + +Chameleon chameleon; + +struct E_Step { + float extrude; + feedRate_t feedRate; +}; + +// Change tools the Chameleon 3D way +void Chameleon::tool_change(const uint8_t index) { + const uint8_t switches = active_extruder ^ index; + if (!switches) return; + + ui.status_printf(0, GET_TEXT_F(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); + + #ifdef CHAMELEON_TOOLCHANGE_Y + current_position.y = CHAMELEON_TOOLCHANGE_Y; + #endif + #ifdef CHAMELEON_TOOLCHANGE_Z + NOLESS(current_position.z, CHAMELEON_TOOLCHANGE_Z); + line_to_current_position(5000); + #endif + if (switches & 0x1) { + current_position.x = CHAMELEON_BUTTON1_X + (X_CENTER > (CHAMELEON_BUTTON1_X)) ? 10 : -10; + } + else { + #if EXTRUDERS > 2 + if (switches & 0x2) + current_position.x = CHAMELEON_BUTTON2_X + (X_CENTER > (CHAMELEON_BUTTON2_X)) ? 10 : -10; + #endif + } + line_to_current_position(5000); + + static constexpr E_Step ramming_sequence[] PROGMEM = { CHAMELEON_RAMMING_SEQUENCE }; + execute_extruder_sequence(ramming_sequence, COUNT(ramming_sequence)); + + toggle(switches); + + active_extruder = index; + + ui.reset_status(); +} + +// Execute a list of E moves +void Chameleon::execute_extruder_sequence(const E_Step * const sequence, const uint8_t steps) { + planner.synchronize(); + stepper.enable_extruder(); + + const E_Step *step = sequence; + + for (uint8_t i = 0; i < steps; ++i) { + const float es = pgm_read_float(&(step->extrude)); + const uint16_t fr_or_ms = pgm_read_float(&(step->feedRate)); + + DEBUG_ECHO_MSG("Move E", es, " @ ", fr_or_ms); + + if (es) { + current_position.e += es; + line_to_current_position(MMM_TO_MMS(fr_or_ms)); + planner.synchronize(); + } + else + safe_delay(fr_or_ms); + + step++; + } + + // Reset E to 0 for the new extruder tool + current_position.e = 0; + sync_plan_position_e(); + + stepper.disable_extruder(); +} + +// Bump the switches needed to change feeders +void Chameleon::toggle(const uint8_t switches) { + if (switches & 0x1) { + current_position.x = CHAMELEON_BUTTON1_X; + line_to_current_position(2000); + current_position.x += (X_CENTER > (CHAMELEON_BUTTON1_X)) ? 10 : -10; + line_to_current_position(2000); + } + #if EXTRUDERS > 2 + if (switches & 0x2) { + current_position.x = CHAMELEON_BUTTON2_X; + line_to_current_position(2000); + current_position.x += (X_CENTER > (CHAMELEON_BUTTON2_X)) ? 10 : -10; + line_to_current_position(2000); + } + #endif + planner.synchronize(); +} + +#endif // HAS_CHAMELEON diff --git a/Marlin/src/feature/mmu/chameleon.h b/Marlin/src/feature/mmu/chameleon.h new file mode 100644 index 000000000000..1a2597741f1b --- /dev/null +++ b/Marlin/src/feature/mmu/chameleon.h @@ -0,0 +1,38 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include + +struct E_Step; + +class Chameleon { + public: + Chameleon() {} + static void tool_change(const uint8_t new_tool); + + private: + static void execute_extruder_sequence(const E_Step * const sequence, const uint8_t steps); + static void toggle(const uint8_t switches); +}; + +extern Chameleon chameleon; diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 2c7420045531..30342735cef6 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -89,6 +89,7 @@ #define _PRUSA_MMU1 1 #define _PRUSA_MMU2 2 #define _PRUSA_MMU2S 3 + #define _CHAMELEON 4 #define _EXTENDABLE_EMU_MMU2 12 #define _EXTENDABLE_EMU_MMU2S 13 #define _MMU CAT(_,MMU_MODEL) @@ -100,6 +101,8 @@ #elif _MMU % 10 == _PRUSA_MMU2S #define HAS_PRUSA_MMU2 1 #define HAS_PRUSA_MMU2S 1 + #elif MMU_MODEL == CHAMELEON + #define HAS_CHAMELEON 1 #endif #if _MMU == _EXTENDABLE_EMU_MMU2 || _MMU == _EXTENDABLE_EMU_MMU2S #define HAS_EXTENDABLE_MMU 1 @@ -109,6 +112,7 @@ #undef _PRUSA_MMU1 #undef _PRUSA_MMU2 #undef _PRUSA_MMU2S + #undef _CHAMELEON #undef _EXTENDABLE_EMU_MMU2 #undef _EXTENDABLE_EMU_MMU2S #endif @@ -144,7 +148,7 @@ #define E_STEPPERS EXTRUDERS #define E_MANUAL EXTRUDERS -#elif HAS_PRUSA_MMU2 // Průša Multi-Material Unit v2 +#elif HAS_PRUSA_MMU2 || HAS_CHAMELEON // Multi-Material Unit #define E_STEPPERS 1 #define E_MANUAL 1 diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index eaba158da898..681f89cf9475 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -618,13 +618,22 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #endif #endif +#if HAS_CHAMELEON + #if EXTRUDERS > 32 + #undef SINGLENOZZLE + #error "CHAMELEON only supports up to 32 EXTRUDERS. Please update your Configuration." + #endif +#endif + /** * Options only for EXTRUDERS > 1 */ #if HAS_MULTI_EXTRUDER #ifndef MAX_EXTRUDERS - #if HAS_EXTENDABLE_MMU + #if HAS_CHAMELEON + #define MAX_EXTRUDERS 32 + #elif HAS_EXTENDABLE_MMU #define MAX_EXTRUDERS 15 #else #define MAX_EXTRUDERS 8 diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h index e82ab66e00d0..9e9f6f9c7b2e 100644 --- a/Marlin/src/module/stepper/indirection.h +++ b/Marlin/src/module/stepper/indirection.h @@ -587,6 +587,12 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define FWD_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? HIGH : LOW ); }while(0) #define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? LOW : HIGH); }while(0) +#elif ENABLED(CHAMELEON) // One multiplexed stepper driver, reversed on T2/T3, T6/T7, T10/T11, etc. + + #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V) + #define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 1) ? HIGH : LOW ); }while(0) + #define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 1) ? LOW : HIGH); }while(0) + #elif E_STEPPERS > 1 #if E_STEPPERS > 7 diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index b5cacc2f3bb9..ba6e2ceeda14 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -80,6 +80,8 @@ #include "../feature/mmu/mmu.h" #elif HAS_PRUSA_MMU2 #include "../feature/mmu/mmu2.h" +#elif HAS_CHAMELEON + #include "../feature/mmu/chameleon.h" #endif #if HAS_MARLINUI_MENU @@ -1122,6 +1124,12 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { mixer.T(new_tool); #endif + #elif HAS_CHAMELEON + + UNUSED(no_move); + + chameleon.tool_change(new_tool); + #elif HAS_PRUSA_MMU2 UNUSED(no_move); diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index c41e73640d44..06caaa89b6ff 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -40,20 +40,20 @@ exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 5 | RRDFGSC | UBL | LIN_ADVANCE ..." # Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language # use_example_configs AnimationExample -opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO LCD_LANGUAGE jp_kana DEFAULT_EJERK 10 \ - EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 5 TEMP_SENSOR_3 20 TEMP_SENSOR_4 1000 TEMP_SENSOR_BED 1 +opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO \ + EXTRUDERS 8 TEMP_SENSOR_BED 1 MMU_MODEL CHAMELEON DEFAULT_EJERK 10 LCD_LANGUAGE jp_kana opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER LIGHTWEIGHT_UI SHOW_CUSTOM_BOOTSCREEN BOOT_MARLIN_LOGO_SMALL \ SET_PROGRESS_MANUALLY SET_PROGRESS_PERCENT PRINT_PROGRESS_SHOW_DECIMALS SHOW_REMAINING_TIME STATUS_MESSAGE_SCROLLING SCROLL_LONG_FILENAMES \ SDSUPPORT LONG_FILENAME_WRITE_SUPPORT SDCARD_SORT_ALPHA NO_SD_AUTOSTART USB_FLASH_DRIVE_SUPPORT CANCEL_OBJECTS \ Z_PROBE_SLED AUTO_BED_LEVELING_UBL UBL_HILBERT_CURVE UBL_TILT_ON_MESH_POINTS UBL_TILT_ON_MESH_POINTS_3POINT \ RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_VALIDATION ENABLE_LEVELING_FADE_HEIGHT \ EEPROM_SETTINGS EEPROM_CHITCHAT GCODE_MACROS CUSTOM_MENU_MAIN \ - MULTI_NOZZLE_DUPLICATION CLASSIC_JERK LIN_ADVANCE QUICK_HOME \ + NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE CLASSIC_JERK LIN_ADVANCE QUICK_HOME \ NANODLP_Z_SYNC I2C_POSITION_ENCODERS M114_DETAIL \ SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \ - BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING BABYSTEP_HOTEND_Z_OFFSET BABYSTEP_DISPLAY_TOTAL + BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING BABYSTEP_DISPLAY_TOTAL opt_disable SEGMENT_LEVELED_MOVES -exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 5 | RRDFGSC | UBL | LIN_ADVANCE | Sled Probe | Skew | JP-Kana | Babystep offsets ..." "$3" +exec_test $1 $2 "Azteeg X3 Pro | Chameleon (x8) | RRDFGSC | UBL | LIN_ADVANCE | Sled Probe | Skew | JP-Kana | Babystep offsets ..." "$3" # # 5 runout sensors with distinct states diff --git a/ini/features.ini b/ini/features.ini index 4baa2566f04d..f4e8b416b0c6 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -258,6 +258,7 @@ HAS_MEATPACK = build_src_filter=+ + HAS_PRUSA_MMU1 = build_src_filter=+ HAS_PRUSA_MMU2 = build_src_filter=+ + +HAS_CHAMELEON = build_src_filter=+ PASSWORD_FEATURE = build_src_filter=+ + ADVANCED_PAUSE_FEATURE = build_src_filter=+ + CONFIGURE_FILAMENT_CHANGE = build_src_filter=+