|
|
@ -294,6 +294,7 @@ static char command_queue[BUFSIZE][MAX_CMD_SIZE]; |
|
|
|
#endif |
|
|
|
|
|
|
|
const float homing_feedrate[] = HOMING_FEEDRATE; |
|
|
|
|
|
|
|
bool axis_relative_modes[] = AXIS_RELATIVE_MODES; |
|
|
|
int feedrate_multiplier = 100; //100->1 200->2
|
|
|
|
int saved_feedrate_multiplier; |
|
|
@ -490,6 +491,10 @@ static uint8_t target_extruder; |
|
|
|
static bool filament_ran_out = false; |
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(FILAMENT_CHANGE_FEATURE) |
|
|
|
FilamentChangeMenuResponse filament_change_menu_response; |
|
|
|
#endif |
|
|
|
|
|
|
|
static bool send_ok[BUFSIZE]; |
|
|
|
|
|
|
|
#if HAS_SERVOS |
|
|
@ -1564,9 +1569,8 @@ inline void line_to_z(float zPosition) { |
|
|
|
inline void line_to_destination(float mm_m) { |
|
|
|
planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], mm_m / 60, active_extruder); |
|
|
|
} |
|
|
|
inline void line_to_destination() { |
|
|
|
line_to_destination(feedrate); |
|
|
|
} |
|
|
|
inline void line_to_destination() { line_to_destination(feedrate); } |
|
|
|
|
|
|
|
/**
|
|
|
|
* sync_plan_position |
|
|
|
* Set planner / stepper positions to the cartesian current_position. |
|
|
@ -3123,7 +3127,7 @@ inline void gcode_G28() { |
|
|
|
enum MeshLevelingState { MeshReport, MeshStart, MeshNext, MeshSet, MeshSetZOffset, MeshReset }; |
|
|
|
|
|
|
|
inline void _mbl_goto_xy(float x, float y) { |
|
|
|
saved_feedrate = feedrate; |
|
|
|
float old_feedrate = feedrate; |
|
|
|
feedrate = homing_feedrate[X_AXIS]; |
|
|
|
|
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z |
|
|
@ -3144,7 +3148,7 @@ inline void gcode_G28() { |
|
|
|
line_to_current_position(); |
|
|
|
#endif |
|
|
|
|
|
|
|
feedrate = saved_feedrate; |
|
|
|
feedrate = old_feedrate; |
|
|
|
stepper.synchronize(); |
|
|
|
} |
|
|
|
|
|
|
@ -6131,7 +6135,7 @@ inline void gcode_M503() { |
|
|
|
|
|
|
|
#endif // HAS_BED_PROBE
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
#if ENABLED(FILAMENT_CHANGE_FEATURE) |
|
|
|
|
|
|
|
/**
|
|
|
|
* M600: Pause for filament change |
|
|
@ -6153,129 +6157,160 @@ inline void gcode_M503() { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Show initial message and wait for synchronize steppers
|
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_INIT); |
|
|
|
stepper.synchronize(); |
|
|
|
|
|
|
|
float lastpos[NUM_AXIS]; |
|
|
|
#if ENABLED(DELTA) |
|
|
|
float fr60 = feedrate / 60; |
|
|
|
#endif |
|
|
|
|
|
|
|
for (int i = 0; i < NUM_AXIS; i++) |
|
|
|
// Save current position of all axes
|
|
|
|
for (uint8_t i = 0; i < NUM_AXIS; i++) |
|
|
|
lastpos[i] = destination[i] = current_position[i]; |
|
|
|
|
|
|
|
// Define runplan for move axes
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
#define RUNPLAN calculate_delta(destination); \ |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], fr60, active_extruder); |
|
|
|
#define RUNPLAN(RATE) calculate_delta(destination); \ |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], RATE, active_extruder); |
|
|
|
#else |
|
|
|
#define RUNPLAN line_to_destination(); |
|
|
|
#define RUNPLAN(RATE) line_to_destination(RATE * 60); |
|
|
|
#endif |
|
|
|
|
|
|
|
//retract by E
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
|
|
|
|
// Initial retract before move to filament change position
|
|
|
|
if (code_seen('E')) destination[E_AXIS] += code_value_axis_units(E_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_FIRSTRETRACT |
|
|
|
else destination[E_AXIS] += FILAMENTCHANGE_FIRSTRETRACT; |
|
|
|
#if defined(FILAMENT_CHANGE_RETRACT_LENGTH) && FILAMENT_CHANGE_RETRACT_LENGTH > 0 |
|
|
|
else destination[E_AXIS] -= FILAMENT_CHANGE_RETRACT_LENGTH; |
|
|
|
#endif |
|
|
|
|
|
|
|
RUNPLAN; |
|
|
|
RUNPLAN(FILAMENT_CHANGE_RETRACT_FEEDRATE); |
|
|
|
|
|
|
|
//lift Z
|
|
|
|
if (code_seen('Z')) destination[Z_AXIS] += code_value_axis_units(Z_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_ZADD |
|
|
|
else destination[Z_AXIS] += FILAMENTCHANGE_ZADD; |
|
|
|
// Lift Z axis
|
|
|
|
float z_lift = code_seen('Z') ? code_value_axis_units(Z_AXIS) : |
|
|
|
#if defined(FILAMENT_CHANGE_Z_ADD) && FILAMENT_CHANGE_Z_ADD > 0 |
|
|
|
FILAMENT_CHANGE_Z_ADD |
|
|
|
#else |
|
|
|
0 |
|
|
|
#endif |
|
|
|
; |
|
|
|
|
|
|
|
RUNPLAN; |
|
|
|
if (z_lift > 0) { |
|
|
|
destination[Z_AXIS] += z_lift; |
|
|
|
NOMORE(destination[Z_AXIS], Z_MAX_POS); |
|
|
|
RUNPLAN(FILAMENT_CHANGE_Z_FEEDRATE); |
|
|
|
} |
|
|
|
|
|
|
|
//move xy
|
|
|
|
// Move XY axes to filament exchange position
|
|
|
|
if (code_seen('X')) destination[X_AXIS] = code_value_axis_units(X_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_XPOS |
|
|
|
else destination[X_AXIS] = FILAMENTCHANGE_XPOS; |
|
|
|
#ifdef FILAMENT_CHANGE_X_POS |
|
|
|
else destination[X_AXIS] = FILAMENT_CHANGE_X_POS; |
|
|
|
#endif |
|
|
|
|
|
|
|
if (code_seen('Y')) destination[Y_AXIS] = code_value_axis_units(Y_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_YPOS |
|
|
|
else destination[Y_AXIS] = FILAMENTCHANGE_YPOS; |
|
|
|
#ifdef FILAMENT_CHANGE_Y_POS |
|
|
|
else destination[Y_AXIS] = FILAMENT_CHANGE_Y_POS; |
|
|
|
#endif |
|
|
|
|
|
|
|
RUNPLAN; |
|
|
|
RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE); |
|
|
|
|
|
|
|
stepper.synchronize(); |
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_UNLOAD); |
|
|
|
|
|
|
|
// Unload filament
|
|
|
|
if (code_seen('L')) destination[E_AXIS] += code_value_axis_units(E_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_FINALRETRACT |
|
|
|
else destination[E_AXIS] += FILAMENTCHANGE_FINALRETRACT; |
|
|
|
#if defined(FILAMENT_CHANGE_UNLOAD_LENGTH) && FILAMENT_CHANGE_UNLOAD_LENGTH > 0 |
|
|
|
else destination[E_AXIS] -= FILAMENT_CHANGE_UNLOAD_LENGTH; |
|
|
|
#endif |
|
|
|
|
|
|
|
RUNPLAN; |
|
|
|
RUNPLAN(FILAMENT_CHANGE_UNLOAD_FEEDRATE); |
|
|
|
|
|
|
|
//finish moves
|
|
|
|
// Synchronize steppers and then disable extruders steppers for manual filament changing
|
|
|
|
stepper.synchronize(); |
|
|
|
//disable extruder steppers so filament can be removed
|
|
|
|
disable_e0(); |
|
|
|
disable_e1(); |
|
|
|
disable_e2(); |
|
|
|
disable_e3(); |
|
|
|
delay(100); |
|
|
|
LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE); |
|
|
|
#if DISABLED(AUTO_FILAMENT_CHANGE) |
|
|
|
|
|
|
|
millis_t next_tick = 0; |
|
|
|
#endif |
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER); |
|
|
|
|
|
|
|
// Wait for filament insert by user and press button
|
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_INSERT); |
|
|
|
|
|
|
|
while (!lcd_clicked()) { |
|
|
|
#if DISABLED(AUTO_FILAMENT_CHANGE) |
|
|
|
#if HAS_BUZZER |
|
|
|
millis_t ms = millis(); |
|
|
|
if (ELAPSED(ms, next_tick)) { |
|
|
|
lcd_quick_feedback(); |
|
|
|
next_tick = ms + 2500UL; // feedback every 2.5s while waiting
|
|
|
|
if (ms >= next_tick) { |
|
|
|
buzzer.tone(300, 2000); |
|
|
|
next_tick = ms + 2500; // Beep every 2.5s while waiting
|
|
|
|
} |
|
|
|
#endif |
|
|
|
idle(true); |
|
|
|
#else |
|
|
|
current_position[E_AXIS] += AUTO_FILAMENT_CHANGE_LENGTH; |
|
|
|
destination[E_AXIS] = current_position[E_AXIS]; |
|
|
|
line_to_destination(AUTO_FILAMENT_CHANGE_FEEDRATE); |
|
|
|
stepper.synchronize(); |
|
|
|
} |
|
|
|
delay(100); |
|
|
|
while (lcd_clicked()) idle(true); |
|
|
|
delay(100); |
|
|
|
|
|
|
|
// Show load message
|
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_LOAD); |
|
|
|
|
|
|
|
// Load filament
|
|
|
|
if (code_seen('L')) destination[E_AXIS] -= code_value_axis_units(E_AXIS); |
|
|
|
#if defined(FILAMENT_CHANGE_LOAD_LENGTH) && FILAMENT_CHANGE_LOAD_LENGTH > 0 |
|
|
|
else destination[E_AXIS] += FILAMENT_CHANGE_LOAD_LENGTH; |
|
|
|
#endif |
|
|
|
} // while(!lcd_clicked)
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
lcd_quick_feedback(); // click sound feedback
|
|
|
|
|
|
|
|
#if ENABLED(AUTO_FILAMENT_CHANGE) |
|
|
|
current_position[E_AXIS] = 0; |
|
|
|
RUNPLAN(FILAMENT_CHANGE_LOAD_FEEDRATE); |
|
|
|
stepper.synchronize(); |
|
|
|
#endif |
|
|
|
|
|
|
|
//return to normal
|
|
|
|
if (code_seen('L')) destination[E_AXIS] -= code_value_axis_units(E_AXIS); |
|
|
|
#ifdef FILAMENTCHANGE_FINALRETRACT |
|
|
|
else destination[E_AXIS] -= FILAMENTCHANGE_FINALRETRACT; |
|
|
|
#if defined(FILAMENT_CHANGE_EXTRUDE_LENGTH) && FILAMENT_CHANGE_EXTRUDE_LENGTH > 0 |
|
|
|
do { |
|
|
|
// Extrude filament to get into hotend
|
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_EXTRUDE); |
|
|
|
destination[E_AXIS] += FILAMENT_CHANGE_EXTRUDE_LENGTH; |
|
|
|
RUNPLAN(FILAMENT_CHANGE_EXTRUDE_FEEDRATE); |
|
|
|
stepper.synchronize(); |
|
|
|
// Ask user if more filament should be extruded
|
|
|
|
KEEPALIVE_STATE(PAUSED_FOR_USER); |
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_OPTION); |
|
|
|
while (filament_change_menu_response == FILAMENT_CHANGE_RESPONSE_WAIT_FOR) idle(true); |
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
} while (filament_change_menu_response != FILAMENT_CHANGE_RESPONSE_RESUME_PRINT); |
|
|
|
#endif |
|
|
|
|
|
|
|
current_position[E_AXIS] = destination[E_AXIS]; //the long retract of L is compensated by manual filament feeding
|
|
|
|
sync_plan_position_e(); |
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_RESUME); |
|
|
|
|
|
|
|
RUNPLAN; //should do nothing
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
|
|
|
|
lcd_reset_alert_level(); |
|
|
|
// Set extruder to saved position
|
|
|
|
current_position[E_AXIS] = lastpos[E_AXIS]; |
|
|
|
destination[E_AXIS] = lastpos[E_AXIS]; |
|
|
|
planner.set_e_position_mm(current_position[E_AXIS]); |
|
|
|
|
|
|
|
#if ENABLED(DELTA) |
|
|
|
// Move XYZ to starting position, then E
|
|
|
|
calculate_delta(lastpos); |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], fr60, active_extruder); |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], lastpos[E_AXIS], fr60, active_extruder); |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], destination[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder); |
|
|
|
planner.buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], lastpos[E_AXIS], FILAMENT_CHANGE_XY_FEEDRATE, active_extruder); |
|
|
|
#else |
|
|
|
// Move XY to starting position, then Z, then E
|
|
|
|
destination[X_AXIS] = lastpos[X_AXIS]; |
|
|
|
destination[Y_AXIS] = lastpos[Y_AXIS]; |
|
|
|
line_to_destination(); |
|
|
|
RUNPLAN(FILAMENT_CHANGE_XY_FEEDRATE); |
|
|
|
destination[Z_AXIS] = lastpos[Z_AXIS]; |
|
|
|
line_to_destination(); |
|
|
|
destination[E_AXIS] = lastpos[E_AXIS]; |
|
|
|
line_to_destination(); |
|
|
|
RUNPLAN(FILAMENT_CHANGE_Z_FEEDRATE); |
|
|
|
#endif |
|
|
|
stepper.synchronize(); |
|
|
|
|
|
|
|
#if ENABLED(FILAMENT_RUNOUT_SENSOR) |
|
|
|
filament_ran_out = false; |
|
|
|
#endif |
|
|
|
|
|
|
|
// Show status screen
|
|
|
|
lcd_filament_change_show_message(FILAMENT_CHANGE_MESSAGE_STATUS); |
|
|
|
} |
|
|
|
|
|
|
|
#endif // FILAMENTCHANGEENABLE
|
|
|
|
#endif // FILAMENT_CHANGE_FEATURE
|
|
|
|
|
|
|
|
#if ENABLED(DUAL_X_CARRIAGE) |
|
|
|
|
|
|
@ -6464,11 +6499,11 @@ inline void gcode_T(uint8_t tmp_extruder) { |
|
|
|
|
|
|
|
#if HOTENDS > 1 |
|
|
|
|
|
|
|
float stored_feedrate = feedrate; |
|
|
|
float old_feedrate = feedrate; |
|
|
|
|
|
|
|
if (code_seen('F')) { |
|
|
|
float next_feedrate = code_value_axis_units(X_AXIS); |
|
|
|
if (next_feedrate > 0.0) stored_feedrate = feedrate = next_feedrate; |
|
|
|
if (next_feedrate > 0.0) old_feedrate = feedrate = next_feedrate; |
|
|
|
} |
|
|
|
else |
|
|
|
feedrate = XY_PROBE_FEEDRATE; |
|
|
@ -6624,7 +6659,7 @@ inline void gcode_T(uint8_t tmp_extruder) { |
|
|
|
enable_solenoid_on_active_extruder(); |
|
|
|
#endif // EXT_SOLENOID
|
|
|
|
|
|
|
|
feedrate = stored_feedrate; |
|
|
|
feedrate = old_feedrate; |
|
|
|
|
|
|
|
#else // !HOTENDS > 1
|
|
|
|
|
|
|
@ -7232,11 +7267,11 @@ void process_next_command() { |
|
|
|
break; |
|
|
|
#endif // HAS_BED_PROBE
|
|
|
|
|
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
#if ENABLED(FILAMENT_CHANGE_FEATURE) |
|
|
|
case 600: //Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
|
|
|
|
gcode_M600(); |
|
|
|
break; |
|
|
|
#endif // FILAMENTCHANGEENABLE
|
|
|
|
#endif // FILAMENT_CHANGE_FEATURE
|
|
|
|
|
|
|
|
#if ENABLED(DUAL_X_CARRIAGE) |
|
|
|
case 605: |
|
|
@ -7993,14 +8028,14 @@ void disable_all_steppers() { |
|
|
|
* Standard idle routine keeps the machine alive |
|
|
|
*/ |
|
|
|
void idle( |
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
#if ENABLED(FILAMENT_CHANGE_FEATURE) |
|
|
|
bool no_stepper_sleep/*=false*/ |
|
|
|
#endif |
|
|
|
) { |
|
|
|
lcd_update(); |
|
|
|
host_keepalive(); |
|
|
|
manage_inactivity( |
|
|
|
#if ENABLED(FILAMENTCHANGEENABLE) |
|
|
|
#if ENABLED(FILAMENT_CHANGE_FEATURE) |
|
|
|
no_stepper_sleep |
|
|
|
#endif |
|
|
|
); |
|
|
|