diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 119f81415a30d..c9a70967bdedc 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -376,6 +376,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 da9f3a66c688d..af4a2a986a465 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -4352,7 +4352,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 bb2bea2e30282..47cf997042667 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -289,6 +289,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) // Macros for initializing arrays +#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 @@ -551,6 +557,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) @@ -586,6 +603,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 0000000000000..a10daa0f9aa80 --- /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 0000000000000..1a2597741f1b4 --- /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 b069e2d2b173b..79615781e3c12 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -585,6 +585,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 @@ -597,6 +598,8 @@ #elif MMU_MODEL % 10 == PRUSA_MMU2S #define HAS_PRUSA_MMU2 1 #define HAS_PRUSA_MMU2S 1 + #elif MMU_MODEL == CHAMELEON + #define HAS_CHAMELEON 1 #endif #if MMU_MODEL >= EXTENDABLE_EMU_MMU2 #define HAS_EXTENDABLE_MMU 1 @@ -606,6 +609,7 @@ #undef PRUSA_MMU1 #undef PRUSA_MMU2 #undef PRUSA_MMU2S +#undef CHAMELEON #undef EXTENDABLE_EMU_MMU2 #undef EXTENDABLE_EMU_MMU2S @@ -629,14 +633,6 @@ #else #undef EXTRUDERS #define EXTRUDERS 0 - #undef TEMP_SENSOR_0 - #undef TEMP_SENSOR_1 - #undef TEMP_SENSOR_2 - #undef TEMP_SENSOR_3 - #undef TEMP_SENSOR_4 - #undef TEMP_SENSOR_5 - #undef TEMP_SENSOR_6 - #undef TEMP_SENSOR_7 #undef SINGLENOZZLE #undef SWITCHING_EXTRUDER #undef MECHANICAL_SWITCHING_EXTRUDER @@ -690,7 +686,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 @@ -702,7 +698,7 @@ #undef DISABLE_OTHER_EXTRUDERS #endif -// Průša MMU1, MMU(S) 2.0 and EXTENDABLE_EMU_MMU2(S) force SINGLENOZZLE +// Chameleon, Průša MMU1, MMU(S) 2.0, and EXTENDABLE_EMU_MMU2(S) force SINGLENOZZLE #if HAS_MMU #define SINGLENOZZLE #endif @@ -787,6 +783,41 @@ #endif #endif +#if HOTENDS <= 7 + #undef TEMP_SENSOR_7 + #define TEMP_SENSOR_7 0 + #if HOTENDS <= 6 + #undef TEMP_SENSOR_6 + #define TEMP_SENSOR_6 0 + #if HOTENDS <= 5 + #undef TEMP_SENSOR_5 + #define TEMP_SENSOR_5 0 + #if HOTENDS <= 4 + #undef TEMP_SENSOR_4 + #define TEMP_SENSOR_4 0 + #if HOTENDS <= 3 + #undef TEMP_SENSOR_3 + #define TEMP_SENSOR_3 0 + #if HOTENDS <= 2 + #undef TEMP_SENSOR_2 + #define TEMP_SENSOR_2 0 + #if HOTENDS <= 1 + #undef TEMP_SENSOR_1 + #define TEMP_SENSOR_1 0 + #if HOTENDS == 0 + #undef TEMP_SENSOR_0 + #define TEMP_SENSOR_0 0 + #undef TEMP_SENSOR_REDUNDANT + #define TEMP_SENSOR_REDUNDANT 0 + #endif + #endif + #endif + #endif + #endif + #endif + #endif +#endif + /** * Number of Linear Axes (e.g., XYZIJKUVW) * All the logical axes except for the tool (E) axis diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index cfc3b20cd5014..7e2cca7a7e1ad 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -643,13 +643,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 e82ab66e00d06..9e9f6f9c7b2e0 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 4c286c81a0ade..17e184cf4ca89 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -81,6 +81,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 @@ -1106,6 +1108,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 46de664e43b64..2236d078620f1 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -39,20 +39,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 1a3546e575fdc..6b6c355c7b73f 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=+ + + PSU_CONTROL = build_src_filter=+