|  |  | @ -13184,7 +13184,7 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     // SERIAL_ECHOPAIR(" seconds=", seconds);
 |  |  |  |     // SERIAL_ECHOPAIR(" seconds=", seconds);
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // SERIAL_ECHOLNPAIR(" segments=", segments);
 |  |  |  |     // SERIAL_ECHOLNPAIR(" segments=", segments);
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     #if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING) |  |  |  |     #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       // SCARA needs to scale the feed rate from mm/s to degrees/s
 |  |  |  |       // SCARA needs to scale the feed rate from mm/s to degrees/s
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       const float inv_segment_length = min(10.0, float(segments) / cartesian_mm), // 1/mm/segs
 |  |  |  |       const float inv_segment_length = min(10.0, float(segments) / cartesian_mm), // 1/mm/segs
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                   inverse_secs = inv_segment_length * _feedrate_mm_s; |  |  |  |                   inverse_secs = inv_segment_length * _feedrate_mm_s; | 
			
		
	
	
		
		
			
				
					|  |  | @ -13216,30 +13216,25 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       ADJUST_DELTA(raw); // Adjust Z if bed leveling is enabled
 |  |  |  |       ADJUST_DELTA(raw); // Adjust Z if bed leveling is enabled
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING) |  |  |  |       #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // For SCARA scale the feed rate from mm/s to degrees/s
 |  |  |  |         // For SCARA scale the feed rate from mm/s to degrees/s
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // Use ratio between the length of the move and the larger angle change
 |  |  |  |         // Use ratio between the length of the move and the larger angle change
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         const float adiff = abs(delta[A_AXIS] - oldA), |  |  |  |         const float adiff = FABS(delta[A_AXIS] - oldA), bdiff = FABS(delta[B_AXIS] - oldB); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                     bdiff = abs(delta[B_AXIS] - oldB); |  |  |  |         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(adiff, bdiff) * inverse_secs, active_extruder); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], max(adiff, bdiff) * inverse_secs, active_extruder); |  |  |  |         oldA = delta[A_AXIS]; oldB = delta[B_AXIS]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         oldA = delta[A_AXIS]; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         oldB = delta[B_AXIS]; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       #else |  |  |  |       #else | 
			
		
	
		
		
			
				
					
					|  |  |  |         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder); |  |  |  |         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       #endif |  |  |  |       #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Since segment_distance is only approximate,
 |  |  |  |     // Since segment_distance is only approximate,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // the final move must be to the exact destination.
 |  |  |  |     // the final move must be to the exact destination.
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     #if IS_SCARA && ENABLED(SCARA_FEEDRATE_SCALING) |  |  |  |     #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       // For SCARA scale the feed rate from mm/s to degrees/s
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       // With segments > 1 length is 1 segment, otherwise total length
 |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       inverse_kinematics(rtarget); |  |  |  |       inverse_kinematics(rtarget); | 
			
		
	
		
		
			
				
					
					|  |  |  |       ADJUST_DELTA(rtarget); |  |  |  |       ADJUST_DELTA(rtarget); | 
			
		
	
		
		
			
				
					
					|  |  |  |       const float adiff = abs(delta[A_AXIS] - oldA), |  |  |  |       const float adiff = FABS(delta[A_AXIS] - oldA), bdiff = FABS(delta[B_AXIS] - oldB); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                   bdiff = abs(delta[B_AXIS] - oldB); |  |  |  |       planner.buffer_line(delta[A_AXIS], delta[B_AXIS], rtarget[Z_AXIS], rtarget[E_AXIS], HYPOT(adiff, bdiff) * inverse_secs, active_extruder); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], max(adiff, bdiff) * inverse_secs, active_extruder); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     #else |  |  |  |     #else | 
			
		
	
		
		
			
				
					
					|  |  |  |       planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder); |  |  |  |       planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |     #endif |  |  |  |     #endif | 
			
		
	
	
		
		
			
				
					|  |  | @ -13509,7 +13504,7 @@ void prepare_move_to_destination() { | 
			
		
	
		
		
			
				
					
					|  |  |  |      * This is important when there are successive arc motions. |  |  |  |      * This is important when there are successive arc motions. | 
			
		
	
		
		
			
				
					
					|  |  |  |      */ |  |  |  |      */ | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Vector rotation matrix values
 |  |  |  |     // Vector rotation matrix values
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     float arc_target[XYZE]; |  |  |  |     float raw[XYZE]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     const float theta_per_segment = angular_travel / segments, |  |  |  |     const float theta_per_segment = angular_travel / segments, | 
			
		
	
		
		
			
				
					
					|  |  |  |                 linear_per_segment = linear_travel / segments, |  |  |  |                 linear_per_segment = linear_travel / segments, | 
			
		
	
		
		
			
				
					
					|  |  |  |                 extruder_per_segment = extruder_travel / segments, |  |  |  |                 extruder_per_segment = extruder_travel / segments, | 
			
		
	
	
		
		
			
				
					|  |  | @ -13517,10 +13512,10 @@ void prepare_move_to_destination() { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
 |  |  |  |                 cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Initialize the linear axis
 |  |  |  |     // Initialize the linear axis
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     arc_target[l_axis] = current_position[l_axis]; |  |  |  |     raw[l_axis] = current_position[l_axis]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Initialize the extruder axis
 |  |  |  |     // Initialize the extruder axis
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     arc_target[E_AXIS] = current_position[E_AXIS]; |  |  |  |     raw[E_AXIS] = current_position[E_AXIS]; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     const float fr_mm_s = MMS_SCALED(feedrate_mm_s); |  |  |  |     const float fr_mm_s = MMS_SCALED(feedrate_mm_s); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -13530,6 +13525,14 @@ void prepare_move_to_destination() { | 
			
		
	
		
		
			
				
					
					|  |  |  |       int8_t arc_recalc_count = N_ARC_CORRECTION; |  |  |  |       int8_t arc_recalc_count = N_ARC_CORRECTION; | 
			
		
	
		
		
			
				
					
					|  |  |  |     #endif |  |  |  |     #endif | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       // SCARA needs to scale the feed rate from mm/s to degrees/s
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       const float inv_segment_length = 1.0 / (MM_PER_ARC_SEGMENT), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                   inverse_secs = inv_segment_length * fr_mm_s; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       float oldA = stepper.get_axis_position_degrees(A_AXIS), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             oldB = stepper.get_axis_position_degrees(B_AXIS); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
 |  |  |  |     for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       thermalManager.manage_heater(); |  |  |  |       thermalManager.manage_heater(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -13561,19 +13564,43 @@ void prepare_move_to_destination() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         r_Q = -offset[0] * sin_Ti - offset[1] * cos_Ti; |  |  |  |         r_Q = -offset[0] * sin_Ti - offset[1] * cos_Ti; | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // Update arc_target location
 |  |  |  |       // Update raw location
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       arc_target[p_axis] = center_P + r_P; |  |  |  |       raw[p_axis] = center_P + r_P; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       arc_target[q_axis] = center_Q + r_Q; |  |  |  |       raw[q_axis] = center_Q + r_Q; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       arc_target[l_axis] += linear_per_segment; |  |  |  |       raw[l_axis] += linear_per_segment; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       arc_target[E_AXIS] += extruder_per_segment; |  |  |  |       raw[E_AXIS] += extruder_per_segment; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       clamp_to_software_endstops(raw); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       clamp_to_software_endstops(arc_target); |  |  |  |       #if IS_KINEMATIC | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         #if ENABLED(DELTA) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           DELTA_RAW_IK(); // Delta can inline its kinematics
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         #else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           inverse_kinematics(raw); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         ADJUST_DELTA(raw); // Adjust Z if bed leveling is enabled
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       #endif | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       planner.buffer_line_kinematic(arc_target, fr_mm_s, active_extruder); |  |  |  |       #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // For SCARA scale the feed rate from mm/s to degrees/s
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // With segments > 1 length is 1 segment, otherwise total length
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         const float adiff = FABS(delta[A_AXIS] - oldA), bdiff = FABS(delta[B_AXIS] - oldB); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         planner.buffer_line(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(adiff, bdiff) * inverse_secs, active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         oldA = delta[A_AXIS]; oldB = delta[B_AXIS]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       #else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         planner.buffer_line_kinematic(raw, fr_mm_s, active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Ensure last segment arrives at target location.
 |  |  |  |     // Ensure last segment arrives at target location.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #if ENABLED(SCARA_FEEDRATE_SCALING) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       inverse_kinematics(cart); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       ADJUST_DELTA(cart); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       const float adiff = FABS(delta[A_AXIS] - oldA), bdiff = FABS(delta[B_AXIS] - oldB); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       planner.buffer_line(delta[A_AXIS], delta[B_AXIS], cart[Z_AXIS], cart[E_AXIS], HYPOT(adiff, bdiff) * inverse_secs, active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #else | 
			
		
	
		
		
			
				
					
					|  |  |  |       planner.buffer_line_kinematic(cart, fr_mm_s, active_extruder); |  |  |  |       planner.buffer_line_kinematic(cart, fr_mm_s, active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     #endif | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // As far as the parser is concerned, the position is now == target. In reality the
 |  |  |  |     // As far as the parser is concerned, the position is now == target. In reality the
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // motion control system might still be processing the action and the real tool position
 |  |  |  |     // motion control system might still be processing the action and the real tool position
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |