Implement MIXING_EXTRUDER and SWITCHING_EXTRUDER
This commit is contained in:
parent
22b4cff423
commit
05da02f0a2
@ -167,37 +167,63 @@ void manage_inactivity(bool ignore_stepper_queue = false);
|
|||||||
#define disable_z() NOOP
|
#define disable_z() NOOP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_E0_ENABLE
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
#define enable_e0() E0_ENABLE_WRITE( E_ENABLE_ON)
|
|
||||||
#define disable_e0() E0_ENABLE_WRITE(!E_ENABLE_ON)
|
|
||||||
#else
|
|
||||||
#define enable_e0() NOOP
|
|
||||||
#define disable_e0() NOOP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (EXTRUDERS > 1) && HAS_E1_ENABLE
|
/**
|
||||||
#define enable_e1() E1_ENABLE_WRITE( E_ENABLE_ON)
|
* Mixing steppers synchronize their enable (and direction) together
|
||||||
#define disable_e1() E1_ENABLE_WRITE(!E_ENABLE_ON)
|
*/
|
||||||
#else
|
#if MIXING_STEPPERS > 3
|
||||||
|
#define enable_e0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); E3_ENABLE_WRITE( E_ENABLE_ON); }
|
||||||
|
#define disable_e0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); E3_ENABLE_WRITE(!E_ENABLE_ON); }
|
||||||
|
#elif MIXING_STEPPERS > 2
|
||||||
|
#define enable_e0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); }
|
||||||
|
#define disable_e0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); }
|
||||||
|
#else
|
||||||
|
#define enable_e0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); }
|
||||||
|
#define disable_e0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); }
|
||||||
|
#endif
|
||||||
#define enable_e1() NOOP
|
#define enable_e1() NOOP
|
||||||
#define disable_e1() NOOP
|
#define disable_e1() NOOP
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (EXTRUDERS > 2) && HAS_E2_ENABLE
|
|
||||||
#define enable_e2() E2_ENABLE_WRITE( E_ENABLE_ON)
|
|
||||||
#define disable_e2() E2_ENABLE_WRITE(!E_ENABLE_ON)
|
|
||||||
#else
|
|
||||||
#define enable_e2() NOOP
|
#define enable_e2() NOOP
|
||||||
#define disable_e2() NOOP
|
#define disable_e2() NOOP
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (EXTRUDERS > 3) && HAS_E3_ENABLE
|
|
||||||
#define enable_e3() E3_ENABLE_WRITE( E_ENABLE_ON)
|
|
||||||
#define disable_e3() E3_ENABLE_WRITE(!E_ENABLE_ON)
|
|
||||||
#else
|
|
||||||
#define enable_e3() NOOP
|
#define enable_e3() NOOP
|
||||||
#define disable_e3() NOOP
|
#define disable_e3() NOOP
|
||||||
#endif
|
|
||||||
|
#else // !MIXING_EXTRUDER
|
||||||
|
|
||||||
|
#if HAS_E0_ENABLE
|
||||||
|
#define enable_e0() E0_ENABLE_WRITE( E_ENABLE_ON)
|
||||||
|
#define disable_e0() E0_ENABLE_WRITE(!E_ENABLE_ON)
|
||||||
|
#else
|
||||||
|
#define enable_e0() NOOP
|
||||||
|
#define disable_e0() NOOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if E_STEPPERS > 1 && HAS_E1_ENABLE
|
||||||
|
#define enable_e1() E1_ENABLE_WRITE( E_ENABLE_ON)
|
||||||
|
#define disable_e1() E1_ENABLE_WRITE(!E_ENABLE_ON)
|
||||||
|
#else
|
||||||
|
#define enable_e1() NOOP
|
||||||
|
#define disable_e1() NOOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if E_STEPPERS > 2 && HAS_E2_ENABLE
|
||||||
|
#define enable_e2() E2_ENABLE_WRITE( E_ENABLE_ON)
|
||||||
|
#define disable_e2() E2_ENABLE_WRITE(!E_ENABLE_ON)
|
||||||
|
#else
|
||||||
|
#define enable_e2() NOOP
|
||||||
|
#define disable_e2() NOOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if E_STEPPERS > 3 && HAS_E3_ENABLE
|
||||||
|
#define enable_e3() E3_ENABLE_WRITE( E_ENABLE_ON)
|
||||||
|
#define disable_e3() E3_ENABLE_WRITE(!E_ENABLE_ON)
|
||||||
|
#else
|
||||||
|
#define enable_e3() NOOP
|
||||||
|
#define disable_e3() NOOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !MIXING_EXTRUDER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The axis order in all axis related arrays is X, Y, Z, E
|
* The axis order in all axis related arrays is X, Y, Z, E
|
||||||
@ -376,6 +402,10 @@ extern uint8_t active_extruder;
|
|||||||
void print_heaterstates();
|
void print_heaterstates();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
extern float mixing_factor[MIXING_STEPPERS];
|
||||||
|
#endif
|
||||||
|
|
||||||
void calculate_volumetric_multipliers();
|
void calculate_volumetric_multipliers();
|
||||||
|
|
||||||
// Buzzer
|
// Buzzer
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
|
* M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
|
||||||
* M149 - Set temperature units
|
* M149 - Set temperature units
|
||||||
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
|
* M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
|
||||||
|
* M163 - Set a single proportion for a mixing extruder. Requires MIXING_EXTRUDER.
|
||||||
|
* M164 - Save the mix as a virtual extruder. Requires MIXING_EXTRUDER and MIXING_VIRTUAL_TOOLS.
|
||||||
|
* M165 - Set the proportions for a mixing extruder. Use parameters ABCDHI to set the mixing factors. Requires MIXING_EXTRUDER.
|
||||||
* M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
|
* M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
|
||||||
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
|
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
|
||||||
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
|
* M200 - Set filament diameter, D<diameter>, setting E axis units to cubic. (Use S0 to revert to linear units.)
|
||||||
@ -397,17 +400,11 @@ static uint8_t target_extruder;
|
|||||||
|
|
||||||
// Extruder offsets
|
// Extruder offsets
|
||||||
#if HOTENDS > 1
|
#if HOTENDS > 1
|
||||||
#ifndef HOTEND_OFFSET_X
|
|
||||||
#define HOTEND_OFFSET_X { 0 } // X offsets for each extruder
|
|
||||||
#endif
|
|
||||||
#ifndef HOTEND_OFFSET_Y
|
|
||||||
#define HOTEND_OFFSET_Y { 0 } // Y offsets for each extruder
|
|
||||||
#endif
|
|
||||||
float hotend_offset[][HOTENDS] = {
|
float hotend_offset[][HOTENDS] = {
|
||||||
HOTEND_OFFSET_X,
|
HOTEND_OFFSET_X,
|
||||||
HOTEND_OFFSET_Y
|
HOTEND_OFFSET_Y
|
||||||
#if ENABLED(DUAL_X_CARRIAGE)
|
#ifdef HOTEND_OFFSET_Z
|
||||||
, { 0 } // Z offsets for each extruder
|
, HOTEND_OFFSET_Z
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -507,6 +504,13 @@ static uint8_t target_extruder;
|
|||||||
FilamentChangeMenuResponse filament_change_menu_response;
|
FilamentChangeMenuResponse filament_change_menu_response;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
float mixing_factor[MIXING_STEPPERS];
|
||||||
|
#if MIXING_VIRTUAL_TOOLS > 1
|
||||||
|
float mixing_virtual_tool_mix[MIXING_VIRTUAL_TOOLS][MIXING_STEPPERS];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool send_ok[BUFSIZE];
|
static bool send_ok[BUFSIZE];
|
||||||
|
|
||||||
#if HAS_SERVOS
|
#if HAS_SERVOS
|
||||||
@ -952,6 +956,15 @@ void setup() {
|
|||||||
lcd_init();
|
lcd_init();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
|
||||||
|
// Initialize mixing to 100% color 1
|
||||||
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
mixing_factor[i] = (i == 0) ? 1 : 0;
|
||||||
|
for (uint8_t t = 0; t < MIXING_VIRTUAL_TOOLS; t++)
|
||||||
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
mixing_virtual_tool_mix[t][i] = mixing_factor[i];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2544,6 +2557,39 @@ static void homeaxis(AxisEnum axis) {
|
|||||||
|
|
||||||
#endif // FWRETRACT
|
#endif // FWRETRACT
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
|
||||||
|
void normalize_mix() {
|
||||||
|
float mix_total = 0.0;
|
||||||
|
for (int i = 0; i < MIXING_STEPPERS; i++) {
|
||||||
|
float v = mixing_factor[i];
|
||||||
|
if (v < 0) v = mixing_factor[i] = 0;
|
||||||
|
mix_total += v;
|
||||||
|
}
|
||||||
|
// Scale all values if they don't add up to ~1.0
|
||||||
|
if (mix_total < 0.9999 || mix_total > 1.0001) {
|
||||||
|
SERIAL_PROTOCOLLNPGM("Warning: Mix factors must add up to 1.0. Scaling.");
|
||||||
|
float mix_scale = 1.0 / mix_total;
|
||||||
|
for (int i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
mixing_factor[i] *= mix_scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLED(DIRECT_MIXING_IN_G1)
|
||||||
|
// Get mixing parameters from the GCode
|
||||||
|
// Factors that are left out are set to 0
|
||||||
|
// The total "must" be 1.0 (but it will be normalized)
|
||||||
|
void gcode_get_mix() {
|
||||||
|
const char* mixing_codes = "ABCDHI";
|
||||||
|
for (int i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
mixing_factor[i] = code_seen(mixing_codes[i]) ? code_value_float() : 0;
|
||||||
|
|
||||||
|
normalize_mix();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***************************************************************************
|
* ***************************************************************************
|
||||||
* ***************************** G-CODE HANDLING *****************************
|
* ***************************** G-CODE HANDLING *****************************
|
||||||
@ -2572,6 +2618,11 @@ void gcode_get_destination() {
|
|||||||
if(!DEBUGGING(DRYRUN))
|
if(!DEBUGGING(DRYRUN))
|
||||||
print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]);
|
print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Get ABCDHI mixing factors
|
||||||
|
#if ENABLED(MIXING_EXTRUDER) && ENABLED(DIRECT_MIXING_IN_G1)
|
||||||
|
gcode_get_mix();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void unknown_command_error() {
|
void unknown_command_error() {
|
||||||
@ -4733,6 +4784,8 @@ inline void gcode_M109() {
|
|||||||
|
|
||||||
KEEPALIVE_STATE(NOT_BUSY);
|
KEEPALIVE_STATE(NOT_BUSY);
|
||||||
|
|
||||||
|
target_extruder = active_extruder; // for print_heaterstates
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Target temperature might be changed during the loop
|
// Target temperature might be changed during the loop
|
||||||
if (theTarget != thermalManager.degTargetBed()) {
|
if (theTarget != thermalManager.degTargetBed()) {
|
||||||
@ -5258,7 +5311,7 @@ inline void gcode_M200() {
|
|||||||
if (volumetric_enabled) {
|
if (volumetric_enabled) {
|
||||||
filament_size[target_extruder] = code_value_linear_units();
|
filament_size[target_extruder] = code_value_linear_units();
|
||||||
// make sure all extruders have some sane value for the filament size
|
// make sure all extruders have some sane value for the filament size
|
||||||
for (int i = 0; i < EXTRUDERS; i++)
|
for (int i = 0; i < COUNT(filament_size); i++)
|
||||||
if (! filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
|
if (! filament_size[i]) filament_size[i] = DEFAULT_NOMINAL_FILAMENT_DIA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5496,7 +5549,7 @@ inline void gcode_M206() {
|
|||||||
* T<tool>
|
* T<tool>
|
||||||
* X<xoffset>
|
* X<xoffset>
|
||||||
* Y<yoffset>
|
* Y<yoffset>
|
||||||
* Z<zoffset> - Available with DUAL_X_CARRIAGE
|
* Z<zoffset> - Available with DUAL_X_CARRIAGE and SWITCHING_EXTRUDER
|
||||||
*/
|
*/
|
||||||
inline void gcode_M218() {
|
inline void gcode_M218() {
|
||||||
if (get_target_extruder_from_command(218)) return;
|
if (get_target_extruder_from_command(218)) return;
|
||||||
@ -5504,7 +5557,7 @@ inline void gcode_M206() {
|
|||||||
if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value_axis_units(X_AXIS);
|
if (code_seen('X')) hotend_offset[X_AXIS][target_extruder] = code_value_axis_units(X_AXIS);
|
||||||
if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value_axis_units(Y_AXIS);
|
if (code_seen('Y')) hotend_offset[Y_AXIS][target_extruder] = code_value_axis_units(Y_AXIS);
|
||||||
|
|
||||||
#if ENABLED(DUAL_X_CARRIAGE)
|
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
|
||||||
if (code_seen('Z')) hotend_offset[Z_AXIS][target_extruder] = code_value_axis_units(Z_AXIS);
|
if (code_seen('Z')) hotend_offset[Z_AXIS][target_extruder] = code_value_axis_units(Z_AXIS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -5515,7 +5568,7 @@ inline void gcode_M206() {
|
|||||||
SERIAL_ECHO(hotend_offset[X_AXIS][e]);
|
SERIAL_ECHO(hotend_offset[X_AXIS][e]);
|
||||||
SERIAL_CHAR(',');
|
SERIAL_CHAR(',');
|
||||||
SERIAL_ECHO(hotend_offset[Y_AXIS][e]);
|
SERIAL_ECHO(hotend_offset[Y_AXIS][e]);
|
||||||
#if ENABLED(DUAL_X_CARRIAGE)
|
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_EXTRUDER)
|
||||||
SERIAL_CHAR(',');
|
SERIAL_CHAR(',');
|
||||||
SERIAL_ECHO(hotend_offset[Z_AXIS][e]);
|
SERIAL_ECHO(hotend_offset[Z_AXIS][e]);
|
||||||
#endif
|
#endif
|
||||||
@ -6528,6 +6581,60 @@ inline void gcode_M907() {
|
|||||||
|
|
||||||
#endif // HAS_MICROSTEPS
|
#endif // HAS_MICROSTEPS
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* M163: Set a single mix factor for a mixing extruder
|
||||||
|
* This is called "weight" by some systems.
|
||||||
|
*
|
||||||
|
* S[index] The channel index to set
|
||||||
|
* P[float] The mix value
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
inline void gcode_M163() {
|
||||||
|
int mix_index = code_seen('S') ? code_value_int() : 0;
|
||||||
|
float mix_value = code_seen('P') ? code_value_float() : 0.0;
|
||||||
|
if (mix_index < MIXING_STEPPERS) mixing_factor[mix_index] = mix_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MIXING_VIRTUAL_TOOLS > 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* M164: Store the current mix factors as a virtual tool.
|
||||||
|
*
|
||||||
|
* S[index] The virtual tool to store
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
inline void gcode_M164() {
|
||||||
|
int tool_index = code_seen('S') ? code_value_int() : 0;
|
||||||
|
if (tool_index < MIXING_VIRTUAL_TOOLS) {
|
||||||
|
normalize_mix();
|
||||||
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
mixing_virtual_tool_mix[tool_index][i] = mixing_factor[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLED(DIRECT_MIXING_IN_G1)
|
||||||
|
/**
|
||||||
|
* M165: Set multiple mix factors for a mixing extruder.
|
||||||
|
* Factors that are left out will be set to 0.
|
||||||
|
* All factors together must add up to 1.0.
|
||||||
|
*
|
||||||
|
* A[factor] Mix factor for extruder stepper 1
|
||||||
|
* B[factor] Mix factor for extruder stepper 2
|
||||||
|
* C[factor] Mix factor for extruder stepper 3
|
||||||
|
* D[factor] Mix factor for extruder stepper 4
|
||||||
|
* H[factor] Mix factor for extruder stepper 5
|
||||||
|
* I[factor] Mix factor for extruder stepper 6
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
inline void gcode_M165() { gcode_get_mix(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MIXING_EXTRUDER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M999: Restart after being stopped
|
* M999: Restart after being stopped
|
||||||
*
|
*
|
||||||
@ -6548,6 +6655,20 @@ inline void gcode_M999() {
|
|||||||
FlushSerialRequestResend();
|
FlushSerialRequestResend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
|
inline void move_extruder_servo(uint8_t e) {
|
||||||
|
const int angles[2] = SWITCHING_EXTRUDER_SERVO_ANGLES;
|
||||||
|
MOVE_SERVO(SWITCHING_EXTRUDER_SERVO_NR, angles[e]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void invalid_extruder_error(const uint8_t &e) {
|
||||||
|
SERIAL_ECHO_START;
|
||||||
|
SERIAL_CHAR('T');
|
||||||
|
SERIAL_PROTOCOL_F(e, DEC);
|
||||||
|
SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* T0-T3: Switch tool, usually switching extruders
|
* T0-T3: Switch tool, usually switching extruders
|
||||||
*
|
*
|
||||||
@ -6555,14 +6676,20 @@ inline void gcode_M999() {
|
|||||||
* S1 Don't move the tool in XY after change
|
* S1 Don't move the tool in XY after change
|
||||||
*/
|
*/
|
||||||
inline void gcode_T(uint8_t tmp_extruder) {
|
inline void gcode_T(uint8_t tmp_extruder) {
|
||||||
if (tmp_extruder >= EXTRUDERS) {
|
|
||||||
SERIAL_ECHO_START;
|
#if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1
|
||||||
SERIAL_CHAR('T');
|
|
||||||
SERIAL_PROTOCOL_F(tmp_extruder, DEC);
|
if (tmp_extruder >= MIXING_VIRTUAL_TOOLS) {
|
||||||
SERIAL_ECHOLN(MSG_INVALID_EXTRUDER);
|
invalid_extruder_error(tmp_extruder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// T0-Tnnn: Switch virtual tool by changing the mix
|
||||||
|
for (uint8_t j = 0; j < MIXING_STEPPERS; j++)
|
||||||
|
mixing_factor[j] = mixing_virtual_tool_mix[tmp_extruder][j];
|
||||||
|
|
||||||
|
#else //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
|
||||||
|
|
||||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||||
if (DEBUGGING(LEVELING)) {
|
if (DEBUGGING(LEVELING)) {
|
||||||
SERIAL_ECHOLNPGM(">>> gcode_T");
|
SERIAL_ECHOLNPGM(">>> gcode_T");
|
||||||
@ -6572,6 +6699,11 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
|
|
||||||
#if HOTENDS > 1
|
#if HOTENDS > 1
|
||||||
|
|
||||||
|
if (tmp_extruder >= EXTRUDERS) {
|
||||||
|
invalid_extruder_error(tmp_extruder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float old_feedrate = feedrate;
|
float old_feedrate = feedrate;
|
||||||
|
|
||||||
if (code_seen('F')) {
|
if (code_seen('F')) {
|
||||||
@ -6583,6 +6715,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
|
|
||||||
if (tmp_extruder != active_extruder) {
|
if (tmp_extruder != active_extruder) {
|
||||||
bool no_move = code_seen('S') && code_value_bool();
|
bool no_move = code_seen('S') && code_value_bool();
|
||||||
|
|
||||||
if (!no_move && axis_unhomed_error(true, true, true)) {
|
if (!no_move && axis_unhomed_error(true, true, true)) {
|
||||||
SERIAL_ECHOLNPGM("No move on toolchange");
|
SERIAL_ECHOLNPGM("No move on toolchange");
|
||||||
no_move = true;
|
no_move = true;
|
||||||
@ -6604,8 +6737,8 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning()
|
if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() &&
|
||||||
&& (delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder))
|
(delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder))
|
||||||
) {
|
) {
|
||||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||||
if (DEBUGGING(LEVELING)) {
|
if (DEBUGGING(LEVELING)) {
|
||||||
@ -6615,12 +6748,15 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Park old head: 1) raise 2) move to park position 3) lower
|
// Park old head: 1) raise 2) move to park position 3) lower
|
||||||
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT,
|
for (uint8_t i = 0; i < 3; i++)
|
||||||
current_position[E_AXIS], planner.max_feedrate[Z_AXIS], active_extruder);
|
planner.buffer_line(
|
||||||
planner.buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT,
|
i == 0 ? current_position[X_AXIS] : x_home_pos(active_extruder),
|
||||||
current_position[E_AXIS], planner.max_feedrate[X_AXIS], active_extruder);
|
current_position[Y_AXIS],
|
||||||
planner.buffer_line(x_home_pos(active_extruder), current_position[Y_AXIS], current_position[Z_AXIS],
|
current_position[Z_AXIS] + (i == 2 ? 0 : TOOLCHANGE_PARK_ZLIFT),
|
||||||
current_position[E_AXIS], planner.max_feedrate[Z_AXIS], active_extruder);
|
current_position[E_AXIS],
|
||||||
|
planner.max_feedrate[i == 1 ? X_AXIS : Z_AXIS],
|
||||||
|
active_extruder
|
||||||
|
);
|
||||||
stepper.synchronize();
|
stepper.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6670,6 +6806,39 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
// No extra case for AUTO_BED_LEVELING_FEATURE in DUAL_X_CARRIAGE. Does that mean they don't work together?
|
// No extra case for AUTO_BED_LEVELING_FEATURE in DUAL_X_CARRIAGE. Does that mean they don't work together?
|
||||||
#else // !DUAL_X_CARRIAGE
|
#else // !DUAL_X_CARRIAGE
|
||||||
|
|
||||||
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
|
// <0 if the new nozzle is higher, >0 if lower. A bigger raise when lower.
|
||||||
|
float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder],
|
||||||
|
z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0);
|
||||||
|
|
||||||
|
// Always raise by some amount
|
||||||
|
planner.buffer_line(
|
||||||
|
current_position[X_AXIS],
|
||||||
|
current_position[Y_AXIS],
|
||||||
|
current_position[Z_AXIS] + z_raise,
|
||||||
|
current_position[E_AXIS],
|
||||||
|
planner.max_feedrate[Z_AXIS],
|
||||||
|
active_extruder
|
||||||
|
);
|
||||||
|
stepper.synchronize();
|
||||||
|
|
||||||
|
move_extruder_servo(active_extruder);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Move back down, if needed
|
||||||
|
if (z_raise != z_diff) {
|
||||||
|
planner.buffer_line(
|
||||||
|
current_position[X_AXIS],
|
||||||
|
current_position[Y_AXIS],
|
||||||
|
current_position[Z_AXIS] + z_diff,
|
||||||
|
current_position[E_AXIS],
|
||||||
|
planner.max_feedrate[Z_AXIS],
|
||||||
|
active_extruder
|
||||||
|
);
|
||||||
|
stepper.synchronize();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set current_position to the position of the new nozzle.
|
* Set current_position to the position of the new nozzle.
|
||||||
* Offsets are based on linear distance, so we need to get
|
* Offsets are based on linear distance, so we need to get
|
||||||
@ -6796,12 +6965,12 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
|
|
||||||
feedrate = old_feedrate;
|
feedrate = old_feedrate;
|
||||||
|
|
||||||
#else // !HOTENDS > 1
|
#else // HOTENDS <= 1
|
||||||
|
|
||||||
// Set the new active extruder
|
// Set the new active extruder
|
||||||
active_extruder = tmp_extruder;
|
active_extruder = tmp_extruder;
|
||||||
|
|
||||||
#endif
|
#endif // HOTENDS <= 1
|
||||||
|
|
||||||
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
||||||
if (DEBUGGING(LEVELING)) {
|
if (DEBUGGING(LEVELING)) {
|
||||||
@ -6813,6 +6982,8 @@ inline void gcode_T(uint8_t tmp_extruder) {
|
|||||||
SERIAL_ECHO_START;
|
SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOPGM(MSG_ACTIVE_EXTRUDER);
|
SERIAL_ECHOPGM(MSG_ACTIVE_EXTRUDER);
|
||||||
SERIAL_PROTOCOLLN((int)active_extruder);
|
SERIAL_PROTOCOLLN((int)active_extruder);
|
||||||
|
|
||||||
|
#endif //!MIXING_EXTRUDER || MIXING_VIRTUAL_TOOLS <= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7219,6 +7390,22 @@ void process_next_command() {
|
|||||||
|
|
||||||
#endif //EXPERIMENTAL_I2CBUS
|
#endif //EXPERIMENTAL_I2CBUS
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
case 163: // M163 S<int> P<float> set weight for a mixing extruder
|
||||||
|
gcode_M163();
|
||||||
|
break;
|
||||||
|
#if MIXING_VIRTUAL_TOOLS > 1
|
||||||
|
case 164: // M164 S<int> save current mix as a virtual extruder
|
||||||
|
gcode_M164();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if ENABLED(DIRECT_MIXING_IN_G1)
|
||||||
|
case 165: // M165 [ABCDHI]<float> set multiple mix weights
|
||||||
|
gcode_M165();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
case 200: // M200 D<diameter> Set filament diameter and set E axis units to cubic. (Use S0 to revert to linear units.)
|
case 200: // M200 D<diameter> Set filament diameter and set E axis units to cubic. (Use S0 to revert to linear units.)
|
||||||
gcode_M200();
|
gcode_M200();
|
||||||
break;
|
break;
|
||||||
@ -8033,14 +8220,14 @@ void prepare_move_to_destination() {
|
|||||||
nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
|
nextMotorCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s
|
||||||
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || thermalManager.soft_pwm_bed > 0
|
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON || thermalManager.soft_pwm_bed > 0
|
||||||
|| E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled...
|
|| E0_ENABLE_READ == E_ENABLE_ON // If any of the drivers are enabled...
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
|| E1_ENABLE_READ == E_ENABLE_ON
|
|| E1_ENABLE_READ == E_ENABLE_ON
|
||||||
#if HAS_X2_ENABLE
|
#if HAS_X2_ENABLE
|
||||||
|| X2_ENABLE_READ == X_ENABLE_ON
|
|| X2_ENABLE_READ == X_ENABLE_ON
|
||||||
#endif
|
#endif
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
|| E2_ENABLE_READ == E_ENABLE_ON
|
|| E2_ENABLE_READ == E_ENABLE_ON
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
|| E3_ENABLE_READ == E_ENABLE_ON
|
|| E3_ENABLE_READ == E_ENABLE_ON
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -8303,25 +8490,29 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
|
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
|
||||||
if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL))
|
if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL)
|
||||||
if (thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
|
&& thermalManager.degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
|
||||||
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
|
bool oldstatus = E0_ENABLE_READ;
|
||||||
|
enable_e0();
|
||||||
|
#else // !SWITCHING_EXTRUDER
|
||||||
bool oldstatus;
|
bool oldstatus;
|
||||||
switch (active_extruder) {
|
switch (active_extruder) {
|
||||||
case 0:
|
case 0:
|
||||||
oldstatus = E0_ENABLE_READ;
|
oldstatus = E0_ENABLE_READ;
|
||||||
enable_e0();
|
enable_e0();
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
case 1:
|
case 1:
|
||||||
oldstatus = E1_ENABLE_READ;
|
oldstatus = E1_ENABLE_READ;
|
||||||
enable_e1();
|
enable_e1();
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
case 2:
|
case 2:
|
||||||
oldstatus = E2_ENABLE_READ;
|
oldstatus = E2_ENABLE_READ;
|
||||||
enable_e2();
|
enable_e2();
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
case 3:
|
case 3:
|
||||||
oldstatus = E3_ENABLE_READ;
|
oldstatus = E3_ENABLE_READ;
|
||||||
enable_e3();
|
enable_e3();
|
||||||
@ -8330,6 +8521,8 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // !SWITCHING_EXTRUDER
|
||||||
|
|
||||||
float oldepos = current_position[E_AXIS], oldedes = destination[E_AXIS];
|
float oldepos = current_position[E_AXIS], oldedes = destination[E_AXIS];
|
||||||
planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS],
|
planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS],
|
||||||
destination[E_AXIS] + (EXTRUDER_RUNOUT_EXTRUDE) * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS],
|
destination[E_AXIS] + (EXTRUDER_RUNOUT_EXTRUDE) * (EXTRUDER_RUNOUT_ESTEPS) / planner.axis_steps_per_mm[E_AXIS],
|
||||||
@ -8339,19 +8532,22 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
|||||||
planner.set_e_position_mm(oldepos);
|
planner.set_e_position_mm(oldepos);
|
||||||
previous_cmd_ms = ms; // refresh_cmd_timeout()
|
previous_cmd_ms = ms; // refresh_cmd_timeout()
|
||||||
stepper.synchronize();
|
stepper.synchronize();
|
||||||
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
|
E0_ENABLE_WRITE(oldstatus);
|
||||||
|
#else
|
||||||
switch (active_extruder) {
|
switch (active_extruder) {
|
||||||
case 0:
|
case 0:
|
||||||
E0_ENABLE_WRITE(oldstatus);
|
E0_ENABLE_WRITE(oldstatus);
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
case 1:
|
case 1:
|
||||||
E1_ENABLE_WRITE(oldstatus);
|
E1_ENABLE_WRITE(oldstatus);
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
case 2:
|
case 2:
|
||||||
E2_ENABLE_WRITE(oldstatus);
|
E2_ENABLE_WRITE(oldstatus);
|
||||||
break;
|
break;
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
case 3:
|
case 3:
|
||||||
E3_ENABLE_WRITE(oldstatus);
|
E3_ENABLE_WRITE(oldstatus);
|
||||||
break;
|
break;
|
||||||
@ -8359,8 +8555,9 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // !SWITCHING_EXTRUDER
|
||||||
}
|
}
|
||||||
#endif
|
#endif // EXTRUDER_RUNOUT_PREVENT
|
||||||
|
|
||||||
#if ENABLED(DUAL_X_CARRIAGE)
|
#if ENABLED(DUAL_X_CARRIAGE)
|
||||||
// handle delayed move timeout
|
// handle delayed move timeout
|
||||||
@ -8498,6 +8695,6 @@ float calculate_volumetric_multiplier(float diameter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void calculate_volumetric_multipliers() {
|
void calculate_volumetric_multipliers() {
|
||||||
for (int i = 0; i < EXTRUDERS; i++)
|
for (int i = 0; i < COUNT(filament_size); i++)
|
||||||
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
|
volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ void Config_StoreSettings() {
|
|||||||
|
|
||||||
// Save filament sizes
|
// Save filament sizes
|
||||||
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
|
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
|
||||||
if (q < EXTRUDERS) dummy = filament_size[q];
|
if (q < COUNT(filament_size)) dummy = filament_size[q];
|
||||||
EEPROM_WRITE_VAR(i, dummy);
|
EEPROM_WRITE_VAR(i, dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +531,7 @@ void Config_RetrieveSettings() {
|
|||||||
|
|
||||||
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
|
for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) {
|
||||||
EEPROM_READ_VAR(i, dummy);
|
EEPROM_READ_VAR(i, dummy);
|
||||||
if (q < EXTRUDERS) filament_size[q] = dummy;
|
if (q < COUNT(filament_size)) filament_size[q] = dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eeprom_checksum == stored_checksum) {
|
if (eeprom_checksum == stored_checksum) {
|
||||||
|
@ -251,6 +251,9 @@
|
|||||||
#ifndef MSG_PID_C
|
#ifndef MSG_PID_C
|
||||||
#define MSG_PID_C "PID-C"
|
#define MSG_PID_C "PID-C"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MSG_SELECT
|
||||||
|
#define MSG_SELECT "Select"
|
||||||
|
#endif
|
||||||
#ifndef MSG_E1
|
#ifndef MSG_E1
|
||||||
#define MSG_E1 " E1"
|
#define MSG_E1 " E1"
|
||||||
#endif
|
#endif
|
||||||
|
@ -285,6 +285,17 @@
|
|||||||
#define _H3_PINS HEATER_3_PIN, EXTRUDER_3_AUTO_FAN_PIN, marlinAnalogInputToDigitalPin(TEMP_3_PIN),
|
#define _H3_PINS HEATER_3_PIN, EXTRUDER_3_AUTO_FAN_PIN, marlinAnalogInputToDigitalPin(TEMP_3_PIN),
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#elif ENABLED(MIXING_EXTRUDER)
|
||||||
|
#undef _E1_PINS
|
||||||
|
#define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN,
|
||||||
|
#if MIXING_STEPPERS > 2
|
||||||
|
#undef _E2_PINS
|
||||||
|
#define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN,
|
||||||
|
#if MIXING_STEPPERS > 3
|
||||||
|
#undef _E3_PINS
|
||||||
|
#define _E3_PINS E3_STEP_PIN, E3_DIR_PIN, E3_ENABLE_PIN,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BED_PINS HEATER_BED_PIN, marlinAnalogInputToDigitalPin(TEMP_BED_PIN),
|
#define BED_PINS HEATER_BED_PIN, marlinAnalogInputToDigitalPin(TEMP_BED_PIN),
|
||||||
@ -374,15 +385,15 @@
|
|||||||
// The X2 axis, if any, should be the next open extruder port
|
// The X2 axis, if any, should be the next open extruder port
|
||||||
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(X_DUAL_STEPPER_DRIVERS)
|
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(X_DUAL_STEPPER_DRIVERS)
|
||||||
#ifndef X2_STEP_PIN
|
#ifndef X2_STEP_PIN
|
||||||
#define X2_STEP_PIN _EPIN(EXTRUDERS, STEP)
|
#define X2_STEP_PIN _EPIN(E_STEPPERS, STEP)
|
||||||
#define X2_DIR_PIN _EPIN(EXTRUDERS, DIR)
|
#define X2_DIR_PIN _EPIN(E_STEPPERS, DIR)
|
||||||
#define X2_ENABLE_PIN _EPIN(EXTRUDERS, ENABLE)
|
#define X2_ENABLE_PIN _EPIN(E_STEPPERS, ENABLE)
|
||||||
#endif
|
#endif
|
||||||
#undef _X2_PINS
|
#undef _X2_PINS
|
||||||
#define _X2_PINS X2_STEP_PIN, X2_DIR_PIN, X2_ENABLE_PIN,
|
#define _X2_PINS X2_STEP_PIN, X2_DIR_PIN, X2_ENABLE_PIN,
|
||||||
#define Y2_E_INDEX INCREMENT(EXTRUDERS)
|
#define Y2_E_INDEX INCREMENT(E_STEPPERS)
|
||||||
#else
|
#else
|
||||||
#define Y2_E_INDEX EXTRUDERS
|
#define Y2_E_INDEX E_STEPPERS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The Y2 axis, if any, should be the next open extruder port
|
// The Y2 axis, if any, should be the next open extruder port
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
#error "Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu."
|
#error "Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EXTRUDERS > 2 || HOTENDS > 2
|
#if E_STEPPERS > 2 || HOTENDS > 2
|
||||||
#error "Mega Controller supports up to 2 extruders. Comment this line to keep going."
|
#error "Mega Controller supports up to 2 hotends / E-steppers. Comment this line to keep going."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BOARD_NAME "Mega Controller"
|
#define BOARD_NAME "Mega Controller"
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
#error "Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu."
|
#error "Oops! Make sure you have 'Arduino Mega' selected from the 'Tools -> Boards' menu."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EXTRUDERS > 3 || HOTENDS > 3
|
#if E_STEPPERS > 3 || HOTENDS > 3
|
||||||
#error "RUMBA supports up to 3 extruders. Comment this line to keep going."
|
#error "RUMBA supports up to 3 hotends / E-steppers. Comment this line to keep going."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_MACHINE_NAME "Rumba"
|
#define DEFAULT_MACHINE_NAME "Rumba"
|
||||||
|
@ -629,6 +629,12 @@ void Planner::check_axes_activity() {
|
|||||||
// Bail if this is a zero-length block
|
// Bail if this is a zero-length block
|
||||||
if (block->step_event_count <= dropsegments) return;
|
if (block->step_event_count <= dropsegments) return;
|
||||||
|
|
||||||
|
// For a mixing extruder, get a magnified step_event_count for each
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
||||||
|
block->mix_event_count[i] = (mixing_factor[i] < 0.0001) ? 0 : block->step_event_count / mixing_factor[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FAN_COUNT > 0
|
#if FAN_COUNT > 0
|
||||||
for (uint8_t i = 0; i < FAN_COUNT; i++) block->fan_speed[i] = fanSpeeds[i];
|
for (uint8_t i = 0; i < FAN_COUNT; i++) block->fan_speed[i] = fanSpeeds[i];
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,6 +58,10 @@ typedef struct {
|
|||||||
long steps[NUM_AXIS]; // Step count along each axis
|
long steps[NUM_AXIS]; // Step count along each axis
|
||||||
unsigned long step_event_count; // The number of step events required to complete this block
|
unsigned long step_event_count; // The number of step events required to complete this block
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
unsigned long mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
|
||||||
|
#endif
|
||||||
|
|
||||||
long accelerate_until, // The index of the step event on which to stop acceleration
|
long accelerate_until, // The index of the step event on which to stop acceleration
|
||||||
decelerate_after, // The index of the step event on which to start decelerating
|
decelerate_after, // The index of the step event on which to start decelerating
|
||||||
acceleration_rate; // The acceleration rate used for acceleration calculation
|
acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||||
|
@ -95,13 +95,13 @@ volatile unsigned long Stepper::step_events_completed = 0; // The number of step
|
|||||||
volatile unsigned char Stepper::eISR_Rate = 200; // Keep the ISR at a low rate until needed
|
volatile unsigned char Stepper::eISR_Rate = 200; // Keep the ISR at a low rate until needed
|
||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
volatile int Stepper::e_steps[EXTRUDERS];
|
volatile int Stepper::e_steps[E_STEPPERS];
|
||||||
int Stepper::extruder_advance_k = LIN_ADVANCE_K,
|
int Stepper::extruder_advance_k = LIN_ADVANCE_K,
|
||||||
Stepper::final_estep_rate,
|
Stepper::final_estep_rate,
|
||||||
Stepper::current_estep_rate[EXTRUDERS],
|
Stepper::current_estep_rate[E_STEPPERS],
|
||||||
Stepper::current_adv_steps[EXTRUDERS];
|
Stepper::current_adv_steps[E_STEPPERS];
|
||||||
#else
|
#else
|
||||||
long Stepper::e_steps[EXTRUDERS],
|
long Stepper::e_steps[E_STEPPERS],
|
||||||
Stepper::final_advance = 0,
|
Stepper::final_advance = 0,
|
||||||
Stepper::old_advance = 0,
|
Stepper::old_advance = 0,
|
||||||
Stepper::advance_rate,
|
Stepper::advance_rate,
|
||||||
@ -114,6 +114,10 @@ long Stepper::acceleration_time, Stepper::deceleration_time;
|
|||||||
volatile long Stepper::count_position[NUM_AXIS] = { 0 };
|
volatile long Stepper::count_position[NUM_AXIS] = { 0 };
|
||||||
volatile signed char Stepper::count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
|
volatile signed char Stepper::count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
long Stepper::counter_M[MIXING_STEPPERS];
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned short Stepper::acc_step_rate; // needed for deceleration start point
|
unsigned short Stepper::acc_step_rate; // needed for deceleration start point
|
||||||
uint8_t Stepper::step_loops, Stepper::step_loops_nominal;
|
uint8_t Stepper::step_loops, Stepper::step_loops_nominal;
|
||||||
unsigned short Stepper::OCR1A_nominal;
|
unsigned short Stepper::OCR1A_nominal;
|
||||||
@ -179,7 +183,9 @@ volatile long Stepper::endstops_trigsteps[3];
|
|||||||
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
|
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define E_APPLY_STEP(v,Q) E_STEP_WRITE(v)
|
#if DISABLED(MIXING_EXTRUDER)
|
||||||
|
#define E_APPLY_STEP(v,Q) E_STEP_WRITE(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
// intRes = longIn1 * longIn2 >> 24
|
// intRes = longIn1 * longIn2 >> 24
|
||||||
// uses:
|
// uses:
|
||||||
@ -322,8 +328,15 @@ void Stepper::isr() {
|
|||||||
if (current_block) {
|
if (current_block) {
|
||||||
current_block->busy = true;
|
current_block->busy = true;
|
||||||
trapezoid_generator_reset();
|
trapezoid_generator_reset();
|
||||||
counter_X = -(current_block->step_event_count >> 1);
|
|
||||||
counter_Y = counter_Z = counter_E = counter_X;
|
// Initialize Bresenham counters to 1/2 the ceiling
|
||||||
|
counter_X = counter_Y = counter_Z = counter_E = -(current_block->step_event_count >> 1);
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
MIXING_STEPPERS_LOOP(i)
|
||||||
|
counter_M[i] = -(current_block->mix_event_count[i] >> 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
step_events_completed = 0;
|
step_events_completed = 0;
|
||||||
|
|
||||||
#if ENABLED(Z_LATE_ENABLE)
|
#if ENABLED(Z_LATE_ENABLE)
|
||||||
@ -335,7 +348,7 @@ void Stepper::isr() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #if ENABLED(ADVANCE)
|
// #if ENABLED(ADVANCE)
|
||||||
// e_steps[current_block->active_extruder] = 0;
|
// e_steps[TOOL_E_INDEX] = 0;
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -343,7 +356,7 @@ void Stepper::isr() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_block != NULL) {
|
if (current_block) {
|
||||||
|
|
||||||
// Update endstops state, if enabled
|
// Update endstops state, if enabled
|
||||||
#if HAS_BED_PROBE
|
#if HAS_BED_PROBE
|
||||||
@ -363,25 +376,67 @@ void Stepper::isr() {
|
|||||||
counter_E += current_block->steps[E_AXIS];
|
counter_E += current_block->steps[E_AXIS];
|
||||||
if (counter_E > 0) {
|
if (counter_E > 0) {
|
||||||
counter_E -= current_block->step_event_count;
|
counter_E -= current_block->step_event_count;
|
||||||
|
#if DISABLED(MIXING_EXTRUDER)
|
||||||
|
// Don't step E here for mixing extruder
|
||||||
count_position[E_AXIS] += count_direction[E_AXIS];
|
count_position[E_AXIS] += count_direction[E_AXIS];
|
||||||
e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1;
|
e_steps[TOOL_E_INDEX] += motor_direction(E_AXIS) ? -1 : 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
// Step mixing steppers proportionally
|
||||||
|
long dir = motor_direction(E_AXIS) ? -1 : 1;
|
||||||
|
MIXING_STEPPERS_LOOP(j) {
|
||||||
|
counter_m[j] += current_block->steps[E_AXIS];
|
||||||
|
if (counter_m[j] > 0) {
|
||||||
|
counter_m[j] -= current_block->mix_event_count[j];
|
||||||
|
e_steps[j] += dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (current_block->use_advance_lead) {
|
if (current_block->use_advance_lead) {
|
||||||
int delta_adv_steps; //Maybe a char would be enough?
|
int delta_adv_steps = (((long)extruder_advance_k * current_estep_rate[TOOL_E_INDEX]) >> 9) - current_adv_steps[TOOL_E_INDEX];
|
||||||
delta_adv_steps = (((long)extruder_advance_k * current_estep_rate[current_block->active_extruder]) >> 9) - current_adv_steps[current_block->active_extruder];
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
e_steps[current_block->active_extruder] += delta_adv_steps;
|
// Mixing extruders apply advance lead proportionally
|
||||||
current_adv_steps[current_block->active_extruder] += delta_adv_steps;
|
MIXING_STEPPERS_LOOP(j) {
|
||||||
|
int steps = delta_adv_steps * current_block->step_event_count / current_block->mix_event_count[j];
|
||||||
|
e_steps[j] += steps;
|
||||||
|
current_adv_steps[j] += steps;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// For most extruders, advance the single E stepper
|
||||||
|
e_steps[TOOL_E_INDEX] += delta_adv_steps;
|
||||||
|
current_adv_steps[TOOL_E_INDEX] += delta_adv_steps;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif ENABLED(ADVANCE)
|
#elif ENABLED(ADVANCE)
|
||||||
|
|
||||||
|
// Always count the unified E axis
|
||||||
counter_E += current_block->steps[E_AXIS];
|
counter_E += current_block->steps[E_AXIS];
|
||||||
if (counter_E > 0) {
|
if (counter_E > 0) {
|
||||||
counter_E -= current_block->step_event_count;
|
counter_E -= current_block->step_event_count;
|
||||||
e_steps[current_block->active_extruder] += motor_direction(E_AXIS) ? -1 : 1;
|
#if DISABLED(MIXING_EXTRUDER)
|
||||||
|
// Don't step E here for mixing extruder
|
||||||
|
e_steps[TOOL_E_INDEX] += motor_direction(E_AXIS) ? -1 : 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
|
||||||
|
// Step mixing steppers proportionally
|
||||||
|
long dir = motor_direction(E_AXIS) ? -1 : 1;
|
||||||
|
MIXING_STEPPERS_LOOP(j) {
|
||||||
|
counter_m[j] += current_block->steps[E_AXIS];
|
||||||
|
if (counter_m[j] > 0) {
|
||||||
|
counter_m[j] -= current_block->mix_event_count[j];
|
||||||
|
e_steps[j] += dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MIXING_EXTRUDER
|
||||||
|
|
||||||
#endif // ADVANCE or LIN_ADVANCE
|
#endif // ADVANCE or LIN_ADVANCE
|
||||||
|
|
||||||
#define _COUNTER(AXIS) counter_## AXIS
|
#define _COUNTER(AXIS) counter_## AXIS
|
||||||
@ -395,9 +450,22 @@ void Stepper::isr() {
|
|||||||
STEP_ADD(X);
|
STEP_ADD(X);
|
||||||
STEP_ADD(Y);
|
STEP_ADD(Y);
|
||||||
STEP_ADD(Z);
|
STEP_ADD(Z);
|
||||||
|
|
||||||
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
// Keep updating the single E axis
|
||||||
|
counter_E += current_block->steps[E_AXIS];
|
||||||
|
// Tick the counters used for this mix
|
||||||
|
MIXING_STEPPERS_LOOP(j) {
|
||||||
|
// Step mixing steppers (proportionally)
|
||||||
|
counter_M[j] += current_block->steps[E_AXIS];
|
||||||
|
// Step when the counter goes over zero
|
||||||
|
if (counter_M[j] > 0) En_STEP_WRITE(j, !INVERT_E_STEP_PIN);
|
||||||
|
}
|
||||||
|
#else // !MIXING_EXTRUDER
|
||||||
STEP_ADD(E);
|
STEP_ADD(E);
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !ADVANCE && !LIN_ADVANCE
|
||||||
|
|
||||||
#define STEP_IF_COUNTER(AXIS) \
|
#define STEP_IF_COUNTER(AXIS) \
|
||||||
if (_COUNTER(AXIS) > 0) { \
|
if (_COUNTER(AXIS) > 0) { \
|
||||||
@ -409,17 +477,32 @@ void Stepper::isr() {
|
|||||||
STEP_IF_COUNTER(X);
|
STEP_IF_COUNTER(X);
|
||||||
STEP_IF_COUNTER(Y);
|
STEP_IF_COUNTER(Y);
|
||||||
STEP_IF_COUNTER(Z);
|
STEP_IF_COUNTER(Z);
|
||||||
|
|
||||||
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
// Always step the single E axis
|
||||||
|
if (counter_E > 0) {
|
||||||
|
counter_E -= current_block->step_event_count;
|
||||||
|
count_position[E_AXIS] += count_direction[E_AXIS];
|
||||||
|
}
|
||||||
|
MIXING_STEPPERS_LOOP(j) {
|
||||||
|
if (counter_M[j] > 0) {
|
||||||
|
counter_M[j] -= current_block->mix_event_count[j];
|
||||||
|
En_STEP_WRITE(j, INVERT_E_STEP_PIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // !MIXING_EXTRUDER
|
||||||
STEP_IF_COUNTER(E);
|
STEP_IF_COUNTER(E);
|
||||||
#endif
|
#endif
|
||||||
|
#endif // !ADVANCE && !LIN_ADVANCE
|
||||||
|
|
||||||
step_events_completed++;
|
step_events_completed++;
|
||||||
if (step_events_completed >= current_block->step_event_count) break;
|
if (step_events_completed >= current_block->step_event_count) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
||||||
// If we have esteps to execute, fire the next ISR "now"
|
// If we have esteps to execute, fire the next ISR "now"
|
||||||
if (e_steps[current_block->active_extruder]) OCR0A = TCNT0 + 2;
|
if (e_steps[TOOL_E_INDEX]) OCR0A = TCNT0 + 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate new timer value
|
// Calculate new timer value
|
||||||
@ -440,21 +523,41 @@ void Stepper::isr() {
|
|||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
|
|
||||||
if (current_block->use_advance_lead)
|
if (current_block->use_advance_lead)
|
||||||
current_estep_rate[current_block->active_extruder] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
|
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
|
||||||
|
|
||||||
|
if (current_block->use_advance_lead) {
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
MIXING_STEPPERS_LOOP(j)
|
||||||
|
current_estep_rate[j] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
|
||||||
|
#else
|
||||||
|
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)acc_step_rate * current_block->e_speed_multiplier8) >> 8;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#elif ENABLED(ADVANCE)
|
#elif ENABLED(ADVANCE)
|
||||||
|
|
||||||
advance += advance_rate * step_loops;
|
advance += advance_rate * step_loops;
|
||||||
//NOLESS(advance, current_block->advance);
|
//NOLESS(advance, current_block->advance);
|
||||||
|
|
||||||
|
long advance_whole = advance >> 8,
|
||||||
|
advance_factor = advance_whole - old_advance;
|
||||||
|
|
||||||
// Do E steps + advance steps
|
// Do E steps + advance steps
|
||||||
e_steps[current_block->active_extruder] += ((advance >> 8) - old_advance);
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
old_advance = advance >> 8;
|
// ...for mixing steppers proportionally
|
||||||
|
MIXING_STEPPERS_LOOP(j)
|
||||||
|
e_steps[j] += advance_factor * current_block->step_event_count / current_block->mix_event_count[j];
|
||||||
|
#else
|
||||||
|
// ...for the active extruder
|
||||||
|
e_steps[TOOL_E_INDEX] += advance_factor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
old_advance = advance_whole;
|
||||||
|
|
||||||
#endif // ADVANCE or LIN_ADVANCE
|
#endif // ADVANCE or LIN_ADVANCE
|
||||||
|
|
||||||
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
||||||
eISR_Rate = (timer >> 2) * step_loops / abs(e_steps[current_block->active_extruder]);
|
eISR_Rate = (timer >> 2) * step_loops / abs(e_steps[TOOL_E_INDEX]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (step_events_completed > (unsigned long)current_block->decelerate_after) {
|
else if (step_events_completed > (unsigned long)current_block->decelerate_after) {
|
||||||
@ -474,8 +577,14 @@ void Stepper::isr() {
|
|||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
|
|
||||||
if (current_block->use_advance_lead)
|
if (current_block->use_advance_lead) {
|
||||||
current_estep_rate[current_block->active_extruder] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8;
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
MIXING_STEPPERS_LOOP(j)
|
||||||
|
current_estep_rate[j] = ((unsigned long)step_rate * current_block->e_speed_multiplier8 * current_block->step_event_count / current_block->mix_event_count[j]) >> 8;
|
||||||
|
#else
|
||||||
|
current_estep_rate[TOOL_E_INDEX] = ((unsigned long)step_rate * current_block->e_speed_multiplier8) >> 8;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#elif ENABLED(ADVANCE)
|
#elif ENABLED(ADVANCE)
|
||||||
|
|
||||||
@ -483,14 +592,22 @@ void Stepper::isr() {
|
|||||||
NOLESS(advance, final_advance);
|
NOLESS(advance, final_advance);
|
||||||
|
|
||||||
// Do E steps + advance steps
|
// Do E steps + advance steps
|
||||||
uint32_t advance_whole = advance >> 8;
|
long advance_whole = advance >> 8,
|
||||||
e_steps[current_block->active_extruder] += advance_whole - old_advance;
|
advance_factor = advance_whole - old_advance;
|
||||||
|
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
MIXING_STEPPERS_LOOP(j)
|
||||||
|
e_steps[j] += advance_factor * current_block->step_event_count / current_block->mix_event_count[j];
|
||||||
|
#else
|
||||||
|
e_steps[TOOL_E_INDEX] += advance_factor;
|
||||||
|
#endif
|
||||||
|
|
||||||
old_advance = advance_whole;
|
old_advance = advance_whole;
|
||||||
|
|
||||||
#endif // ADVANCE or LIN_ADVANCE
|
#endif // ADVANCE or LIN_ADVANCE
|
||||||
|
|
||||||
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
||||||
eISR_Rate = (timer >> 2) * step_loops / abs(e_steps[current_block->active_extruder]);
|
eISR_Rate = (timer >> 2) * step_loops / abs(e_steps[TOOL_E_INDEX]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -498,9 +615,9 @@ void Stepper::isr() {
|
|||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
|
|
||||||
if (current_block->use_advance_lead)
|
if (current_block->use_advance_lead)
|
||||||
current_estep_rate[current_block->active_extruder] = final_estep_rate;
|
current_estep_rate[TOOL_E_INDEX] = final_estep_rate;
|
||||||
|
|
||||||
eISR_Rate = (OCR1A_nominal >> 2) * step_loops_nominal / abs(e_steps[current_block->active_extruder]);
|
eISR_Rate = (OCR1A_nominal >> 2) * step_loops_nominal / abs(e_steps[TOOL_E_INDEX]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -537,7 +654,7 @@ void Stepper::isr() {
|
|||||||
E## INDEX ##_DIR_WRITE(INVERT_E## INDEX ##_DIR); \
|
E## INDEX ##_DIR_WRITE(INVERT_E## INDEX ##_DIR); \
|
||||||
e_steps[INDEX]++; \
|
e_steps[INDEX]++; \
|
||||||
} \
|
} \
|
||||||
else if (e_steps[INDEX] > 0) { \
|
else { \
|
||||||
E## INDEX ##_DIR_WRITE(!INVERT_E## INDEX ##_DIR); \
|
E## INDEX ##_DIR_WRITE(!INVERT_E## INDEX ##_DIR); \
|
||||||
e_steps[INDEX]--; \
|
e_steps[INDEX]--; \
|
||||||
} \
|
} \
|
||||||
@ -547,11 +664,11 @@ void Stepper::isr() {
|
|||||||
// Step all E steppers that have steps
|
// Step all E steppers that have steps
|
||||||
for (uint8_t i = 0; i < step_loops; i++) {
|
for (uint8_t i = 0; i < step_loops; i++) {
|
||||||
STEP_E_ONCE(0);
|
STEP_E_ONCE(0);
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
STEP_E_ONCE(1);
|
STEP_E_ONCE(1);
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
STEP_E_ONCE(2);
|
STEP_E_ONCE(2);
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
STEP_E_ONCE(3);
|
STEP_E_ONCE(3);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -730,18 +847,12 @@ void Stepper::init() {
|
|||||||
|
|
||||||
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
|
||||||
|
|
||||||
#if ENABLED(LIN_ADVANCE)
|
for (int i = 0; i < E_STEPPERS; i++) {
|
||||||
|
|
||||||
for (int i = 0; i < EXTRUDERS; i++) {
|
|
||||||
e_steps[i] = 0;
|
e_steps[i] = 0;
|
||||||
|
#if ENABLED(LIN_ADVANCE)
|
||||||
current_adv_steps[i] = 0;
|
current_adv_steps[i] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
#elif ENABLED(ADVANCE)
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < EXTRUDERS; i++) e_steps[i] = 0;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(TCCR0A) && defined(WGM01)
|
#if defined(TCCR0A) && defined(WGM01)
|
||||||
CBI(TCCR0A, WGM01);
|
CBI(TCCR0A, WGM01);
|
||||||
|
@ -107,15 +107,15 @@ class Stepper {
|
|||||||
static unsigned char old_OCR0A;
|
static unsigned char old_OCR0A;
|
||||||
static volatile unsigned char eISR_Rate;
|
static volatile unsigned char eISR_Rate;
|
||||||
#if ENABLED(LIN_ADVANCE)
|
#if ENABLED(LIN_ADVANCE)
|
||||||
static volatile int e_steps[EXTRUDERS];
|
static volatile int e_steps[E_STEPPERS];
|
||||||
static int extruder_advance_k;
|
static int extruder_advance_k;
|
||||||
static int final_estep_rate;
|
static int final_estep_rate;
|
||||||
static int current_estep_rate[EXTRUDERS]; // Actual extruder speed [steps/s]
|
static int current_estep_rate[E_STEPPERS]; // Actual extruder speed [steps/s]
|
||||||
static int current_adv_steps[EXTRUDERS]; // The amount of current added esteps due to advance.
|
static int current_adv_steps[E_STEPPERS]; // The amount of current added esteps due to advance.
|
||||||
// i.e., the current amount of pressure applied
|
// i.e., the current amount of pressure applied
|
||||||
// to the spring (=filament).
|
// to the spring (=filament).
|
||||||
#else
|
#else
|
||||||
static long e_steps[EXTRUDERS];
|
static long e_steps[E_STEPPERS];
|
||||||
static long advance_rate, advance, final_advance;
|
static long advance_rate, advance, final_advance;
|
||||||
static long old_advance;
|
static long old_advance;
|
||||||
#endif
|
#endif
|
||||||
@ -147,6 +147,16 @@ class Stepper {
|
|||||||
//
|
//
|
||||||
static volatile signed char count_direction[NUM_AXIS];
|
static volatile signed char count_direction[NUM_AXIS];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mixing extruder mix counters
|
||||||
|
//
|
||||||
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
|
static long counter_M[MIXING_STEPPERS];
|
||||||
|
#define MIXING_STEPPERS_LOOP(VAR) \
|
||||||
|
for (uint8_t VAR = 0; VAR < MIXING_STEPPERS; VAR++) \
|
||||||
|
if (current_block->mix_event_count[VAR])
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -315,12 +325,25 @@ class Stepper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLED(ADVANCE)
|
#if ENABLED(ADVANCE)
|
||||||
|
|
||||||
advance = current_block->initial_advance;
|
advance = current_block->initial_advance;
|
||||||
final_advance = current_block->final_advance;
|
final_advance = current_block->final_advance;
|
||||||
|
|
||||||
// Do E steps + advance steps
|
// Do E steps + advance steps
|
||||||
e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
|
#if ENABLED(MIXING_EXTRUDER)
|
||||||
old_advance = advance >>8;
|
long advance_factor = (advance >> 8) - old_advance;
|
||||||
|
// ...for mixing steppers proportionally
|
||||||
|
MIXING_STEPPERS_LOOP(j)
|
||||||
|
e_steps[j] += advance_factor * current_block->step_event_count / current_block->mix_event_count[j];
|
||||||
|
#else
|
||||||
|
// ...for the active extruder
|
||||||
|
e_steps[TOOL_E_INDEX] += ((advance >> 8) - old_advance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
old_advance = advance >> 8;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
deceleration_time = 0;
|
deceleration_time = 0;
|
||||||
// step_rate to timer interval
|
// step_rate to timer interval
|
||||||
OCR1A_nominal = calc_timer(current_block->nominal_rate);
|
OCR1A_nominal = calc_timer(current_block->nominal_rate);
|
||||||
|
@ -182,26 +182,42 @@
|
|||||||
#define E3_ENABLE_WRITE(STATE) WRITE(E3_ENABLE_PIN,STATE)
|
#define E3_ENABLE_WRITE(STATE) WRITE(E3_ENABLE_PIN,STATE)
|
||||||
#define E3_ENABLE_READ READ(E3_ENABLE_PIN)
|
#define E3_ENABLE_READ READ(E3_ENABLE_PIN)
|
||||||
|
|
||||||
#if EXTRUDERS > 3
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
#define E_STEP_WRITE(v) {switch(current_block->active_extruder){case 3:E3_STEP_WRITE(v);break;case 2:E2_STEP_WRITE(v);break;case 1:E1_STEP_WRITE(v);break;default:E0_STEP_WRITE(v);}}
|
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
||||||
#define NORM_E_DIR() {switch(current_block->active_extruder){case 3:E3_DIR_WRITE(!INVERT_E3_DIR);break;case 2:E2_DIR_WRITE(!INVERT_E2_DIR);break;case 1:E1_DIR_WRITE(!INVERT_E1_DIR);break;default:E0_DIR_WRITE(!INVERT_E0_DIR);}}
|
#define NORM_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? INVERT_E0_DIR : !INVERT_E0_DIR)
|
||||||
#define REV_E_DIR() {switch(current_block->active_extruder){case 3:E3_DIR_WRITE(INVERT_E3_DIR);break;case 2:E2_DIR_WRITE(INVERT_E2_DIR);break;case 1:E1_DIR_WRITE(INVERT_E1_DIR);break;default:E0_DIR_WRITE(INVERT_E0_DIR);}}
|
#define REV_E_DIR() E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR : INVERT_E0_DIR)
|
||||||
|
#elif EXTRUDERS > 3
|
||||||
|
#define E_STEP_WRITE(v) { switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); } }
|
||||||
|
#define NORM_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); } }
|
||||||
|
#define REV_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(INVERT_E3_DIR); } }
|
||||||
#elif EXTRUDERS > 2
|
#elif EXTRUDERS > 2
|
||||||
#define E_STEP_WRITE(v) {switch(current_block->active_extruder){case 2:E2_STEP_WRITE(v);break;case 1:E1_STEP_WRITE(v);break;default:E0_STEP_WRITE(v);}}
|
#define E_STEP_WRITE(v) { switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); } }
|
||||||
#define NORM_E_DIR() {switch(current_block->active_extruder){case 2:E2_DIR_WRITE(!INVERT_E2_DIR);break;case 1:E1_DIR_WRITE(!INVERT_E1_DIR);break;default:E0_DIR_WRITE(!INVERT_E0_DIR);}}
|
#define NORM_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); } }
|
||||||
#define REV_E_DIR() {switch(current_block->active_extruder){case 2:E2_DIR_WRITE(INVERT_E2_DIR);break;case 1:E1_DIR_WRITE(INVERT_E1_DIR);break;default:E0_DIR_WRITE(INVERT_E0_DIR);}}
|
#define REV_E_DIR() { switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(INVERT_E2_DIR); } }
|
||||||
#elif EXTRUDERS > 1
|
#elif EXTRUDERS > 1
|
||||||
#define _E_STEP_WRITE(v) {if(current_block->active_extruder==1){E1_STEP_WRITE(v);}else{E0_STEP_WRITE(v);}}
|
|
||||||
#define _NORM_E_DIR() {if(current_block->active_extruder==1){E1_DIR_WRITE(!INVERT_E1_DIR);}else{E0_DIR_WRITE(!INVERT_E0_DIR);}}
|
|
||||||
#define _REV_E_DIR() {if(current_block->active_extruder==1){E1_DIR_WRITE(INVERT_E1_DIR);}else{E0_DIR_WRITE(INVERT_E0_DIR);}}
|
|
||||||
#if DISABLED(DUAL_X_CARRIAGE)
|
#if DISABLED(DUAL_X_CARRIAGE)
|
||||||
#define E_STEP_WRITE(v) _E_STEP_WRITE(v)
|
#define E_STEP_WRITE(v) { if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }
|
||||||
#define NORM_E_DIR() _NORM_E_DIR()
|
#define NORM_E_DIR() { if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }
|
||||||
#define REV_E_DIR() _REV_E_DIR()
|
#define REV_E_DIR() { if (current_block->active_extruder == 0) { E0_DIR_WRITE(INVERT_E0_DIR); } else { E1_DIR_WRITE(INVERT_E1_DIR); } }
|
||||||
#else
|
#else
|
||||||
#define E_STEP_WRITE(v) {if(extruder_duplication_enabled){E0_STEP_WRITE(v);E1_STEP_WRITE(v);}else _E_STEP_WRITE(v);}
|
#define E_STEP_WRITE(v) { if (extruder_duplication_enabled) { E0_STEP_WRITE(v); E1_STEP_WRITE(v); } else if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }
|
||||||
#define NORM_E_DIR() {if(extruder_duplication_enabled){E0_DIR_WRITE(!INVERT_E0_DIR);E1_DIR_WRITE(!INVERT_E1_DIR);}else _NORM_E_DIR();}
|
#define NORM_E_DIR() { if (extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }
|
||||||
#define REV_E_DIR() {if(extruder_duplication_enabled){E0_DIR_WRITE(INVERT_E0_DIR);E1_DIR_WRITE(INVERT_E1_DIR);}else _REV_E_DIR();}
|
#define REV_E_DIR() { if (extruder_duplication_enabled) { E0_DIR_WRITE(INVERT_E0_DIR); E1_DIR_WRITE(INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE(INVERT_E0_DIR); } else { E1_DIR_WRITE(INVERT_E1_DIR); } }
|
||||||
|
#endif
|
||||||
|
#elif ENABLED(MIXING_EXTRUDER)
|
||||||
|
#define E_STEP_WRITE(v) NOOP /* not used for mixing extruders! */
|
||||||
|
#if MIXING_STEPPERS > 3
|
||||||
|
#define En_STEP_WRITE(n,v) { switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); } }
|
||||||
|
#define NORM_E_DIR() { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); E2_DIR_WRITE(!INVERT_E2_DIR); E3_DIR_WRITE(!INVERT_E3_DIR); }
|
||||||
|
#define REV_E_DIR() { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); E2_DIR_WRITE( INVERT_E2_DIR); E3_DIR_WRITE( INVERT_E3_DIR); }
|
||||||
|
#elif MIXING_STEPPERS > 2
|
||||||
|
#define En_STEP_WRITE(n,v) { switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); } }
|
||||||
|
#define NORM_E_DIR() { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); E2_DIR_WRITE(!INVERT_E2_DIR); }
|
||||||
|
#define REV_E_DIR() { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); E2_DIR_WRITE( INVERT_E2_DIR); }
|
||||||
|
#else
|
||||||
|
#define En_STEP_WRITE(n,v) { switch (n) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); } }
|
||||||
|
#define NORM_E_DIR() { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); }
|
||||||
|
#define REV_E_DIR() { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); }
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
||||||
|
@ -1365,7 +1365,7 @@ void kill_screen(const char* lcd_msg) {
|
|||||||
#endif
|
#endif
|
||||||
static void lcd_move_z() { _lcd_move_xyz(PSTR(MSG_MOVE_Z), Z_AXIS, sw_endstop_min[Z_AXIS], sw_endstop_max[Z_AXIS]); }
|
static void lcd_move_z() { _lcd_move_xyz(PSTR(MSG_MOVE_Z), Z_AXIS, sw_endstop_min[Z_AXIS], sw_endstop_max[Z_AXIS]); }
|
||||||
static void lcd_move_e(
|
static void lcd_move_e(
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
int8_t eindex = -1
|
int8_t eindex = -1
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
@ -1375,7 +1375,7 @@ void kill_screen(const char* lcd_msg) {
|
|||||||
current_position[E_AXIS] += float((int32_t)encoderPosition) * move_menu_scale;
|
current_position[E_AXIS] += float((int32_t)encoderPosition) * move_menu_scale;
|
||||||
encoderPosition = 0;
|
encoderPosition = 0;
|
||||||
manual_move_to_current(E_AXIS
|
manual_move_to_current(E_AXIS
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
, eindex
|
, eindex
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
@ -1383,34 +1383,34 @@ void kill_screen(const char* lcd_msg) {
|
|||||||
}
|
}
|
||||||
if (lcdDrawUpdate) {
|
if (lcdDrawUpdate) {
|
||||||
PGM_P pos_label;
|
PGM_P pos_label;
|
||||||
#if EXTRUDERS == 1
|
#if E_STEPPERS == 1
|
||||||
pos_label = PSTR(MSG_MOVE_E);
|
pos_label = PSTR(MSG_MOVE_E);
|
||||||
#else
|
#else
|
||||||
switch (eindex) {
|
switch (eindex) {
|
||||||
default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break;
|
default: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E1); break;
|
||||||
case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break;
|
case 1: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E2); break;
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break;
|
case 2: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E3); break;
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break;
|
case 3: pos_label = PSTR(MSG_MOVE_E MSG_MOVE_E4); break;
|
||||||
#endif //EXTRUDERS > 3
|
#endif
|
||||||
#endif //EXTRUDERS > 2
|
#endif
|
||||||
}
|
}
|
||||||
#endif //EXTRUDERS > 1
|
#endif
|
||||||
lcd_implementation_drawedit(pos_label, ftostr41sign(current_position[E_AXIS]));
|
lcd_implementation_drawedit(pos_label, ftostr41sign(current_position[E_AXIS]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EXTRUDERS > 1
|
#if E_STEPPERS > 1
|
||||||
static void lcd_move_e0() { lcd_move_e(0); }
|
static void lcd_move_e0() { lcd_move_e(0); }
|
||||||
static void lcd_move_e1() { lcd_move_e(1); }
|
static void lcd_move_e1() { lcd_move_e(1); }
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
static void lcd_move_e2() { lcd_move_e(2); }
|
static void lcd_move_e2() { lcd_move_e(2); }
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
static void lcd_move_e3() { lcd_move_e(3); }
|
static void lcd_move_e3() { lcd_move_e(3); }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif // EXTRUDERS > 1
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -1432,20 +1432,29 @@ void kill_screen(const char* lcd_msg) {
|
|||||||
MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);
|
MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);
|
||||||
MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);
|
MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_menu_scale < 10.0) {
|
if (move_menu_scale < 10.0) {
|
||||||
if (_MOVE_XYZ_ALLOWED) MENU_ITEM(submenu, MSG_MOVE_Z, lcd_move_z);
|
if (_MOVE_XYZ_ALLOWED) MENU_ITEM(submenu, MSG_MOVE_Z, lcd_move_z);
|
||||||
#if EXTRUDERS == 1
|
|
||||||
|
#if ENABLED(SWITCHING_EXTRUDER)
|
||||||
|
if (active_extruder)
|
||||||
|
MENU_ITEM(gcode, MSG_SELECT MSG_E1, PSTR("T0"));
|
||||||
|
else
|
||||||
|
MENU_ITEM(gcode, MSG_SELECT MSG_E2, PSTR("T1"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if E_STEPPERS == 1
|
||||||
MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_e);
|
MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_e);
|
||||||
#else
|
#else
|
||||||
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_e0);
|
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E1, lcd_move_e0);
|
||||||
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_e1);
|
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E2, lcd_move_e1);
|
||||||
#if EXTRUDERS > 2
|
#if E_STEPPERS > 2
|
||||||
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_e2);
|
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E3, lcd_move_e2);
|
||||||
#if EXTRUDERS > 3
|
#if E_STEPPERS > 3
|
||||||
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_e3);
|
MENU_ITEM(submenu, MSG_MOVE_E MSG_MOVE_E4, lcd_move_e3);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif // EXTRUDERS > 1
|
#endif
|
||||||
}
|
}
|
||||||
END_MENU();
|
END_MENU();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user