Merge pull request #2657 from FormerLurker/MK3
Add arc interpolation features (G2/G3) and M214 command for controlling settings
This commit is contained in:
commit
37e1c11099
14 changed files with 366 additions and 197 deletions
|
@ -169,6 +169,10 @@ void Config_PrintSettings(uint8_t level)
|
||||||
echomagic, echomagic, extruder_advance_K);
|
echomagic, echomagic, extruder_advance_K);
|
||||||
#endif //LIN_ADVANCE
|
#endif //LIN_ADVANCE
|
||||||
}
|
}
|
||||||
|
// Arc Interpolation Settings
|
||||||
|
printf_P(PSTR(
|
||||||
|
"%SArc Settings: P:Max length(mm) S:Min length (mm) N:Corrections R:Min segments F:Segments/sec.\n%S M214 P%.2f S%.2f N%d R%d F%d\n"),
|
||||||
|
echomagic, echomagic, cs.mm_per_arc_segment, cs.min_mm_per_arc_segment, cs.n_arc_correction, cs.min_arc_segments, cs.arc_segments_per_sec);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -184,7 +188,7 @@ static_assert (false, "zprobe_zoffset was not initialized in printers in field t
|
||||||
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static_assert (sizeof(M500_conf) == 196, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
static_assert (sizeof(M500_conf) == 209, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
||||||
"or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
|
"or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
|
||||||
"If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
|
"If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
|
||||||
"leave as it is to keep fast code, or reorder struct members to pack more tightly.");
|
"leave as it is to keep fast code, or reorder struct members to pack more tightly.");
|
||||||
|
@ -233,6 +237,11 @@ static const M500_conf default_conf PROGMEM =
|
||||||
{16,16,16,16},
|
{16,16,16,16},
|
||||||
#endif
|
#endif
|
||||||
DEFAULT_TRAVEL_ACCELERATION,
|
DEFAULT_TRAVEL_ACCELERATION,
|
||||||
|
DEFAULT_MM_PER_ARC_SEGMENT,
|
||||||
|
DEFAULT_MIN_MM_PER_ARC_SEGMENT,
|
||||||
|
DEFAULT_N_ARC_CORRECTION,
|
||||||
|
DEFAULT_MIN_ARC_SEGMENTS,
|
||||||
|
DEFAULT_ARC_SEGMENTS_PER_SEC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,6 +282,13 @@ bool Config_RetrieveSettings()
|
||||||
memcpy_P(&cs.max_acceleration_units_per_sq_second_silent[i],&default_conf.max_acceleration_units_per_sq_second_silent[i],sizeof(cs.max_acceleration_units_per_sq_second_silent[i]));
|
memcpy_P(&cs.max_acceleration_units_per_sq_second_silent[i],&default_conf.max_acceleration_units_per_sq_second_silent[i],sizeof(cs.max_acceleration_units_per_sq_second_silent[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Initialize arc interpolation settings if they are not already
|
||||||
|
if (is_uninitialized(&cs.mm_per_arc_segment, sizeof(cs.mm_per_arc_segment))) cs.mm_per_arc_segment = default_conf.mm_per_arc_segment;
|
||||||
|
if (is_uninitialized(&cs.min_mm_per_arc_segment, sizeof(cs.min_mm_per_arc_segment))) cs.min_mm_per_arc_segment = default_conf.min_mm_per_arc_segment;
|
||||||
|
if (is_uninitialized(&cs.n_arc_correction, sizeof(cs.n_arc_correction))) cs.n_arc_correction = default_conf.n_arc_correction;
|
||||||
|
if (is_uninitialized(&cs.min_arc_segments, sizeof(cs.min_arc_segments))) cs.min_arc_segments = default_conf.min_arc_segments;
|
||||||
|
if (is_uninitialized(&cs.arc_segments_per_sec, sizeof(cs.arc_segments_per_sec))) cs.arc_segments_per_sec = default_conf.arc_segments_per_sec;
|
||||||
|
|
||||||
|
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
||||||
|
@ -344,3 +360,4 @@ SERIAL_ECHO_START;
|
||||||
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,12 @@ typedef struct
|
||||||
unsigned long max_acceleration_units_per_sq_second_silent[4];
|
unsigned long max_acceleration_units_per_sq_second_silent[4];
|
||||||
unsigned char axis_ustep_resolution[4];
|
unsigned char axis_ustep_resolution[4];
|
||||||
float travel_acceleration; //!< travel acceleration mm/s^2
|
float travel_acceleration; //!< travel acceleration mm/s^2
|
||||||
|
// Arc Interpolation Settings, configurable via M214
|
||||||
|
float mm_per_arc_segment;
|
||||||
|
float min_mm_per_arc_segment;
|
||||||
|
unsigned char n_arc_correction; // If equal to zero, this is disabled
|
||||||
|
unsigned short min_arc_segments; // If equal to zero, this is disabled
|
||||||
|
unsigned short arc_segments_per_sec; // If equal to zero, this is disabled
|
||||||
} M500_conf;
|
} M500_conf;
|
||||||
|
|
||||||
extern M500_conf cs;
|
extern M500_conf cs;
|
||||||
|
@ -62,5 +68,4 @@ FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_Prin
|
||||||
inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); }
|
inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); }
|
||||||
inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); }
|
inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); }
|
||||||
inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); }
|
inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); }
|
||||||
|
|
||||||
#endif//CONFIG_STORE_H
|
#endif//CONFIG_STORE_H
|
||||||
|
|
|
@ -289,9 +289,7 @@
|
||||||
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging
|
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Arc interpretation settings:
|
// Arc interpretation settings : Moved to the variant files.
|
||||||
#define MM_PER_ARC_SEGMENT 1
|
|
||||||
#define N_ARC_CORRECTION 25
|
|
||||||
|
|
||||||
const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
|
const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
|
||||||
|
|
||||||
|
|
46
Firmware/Marlin_main.cpp
Executable file → Normal file
46
Firmware/Marlin_main.cpp
Executable file → Normal file
|
@ -4162,6 +4162,7 @@ extern uint8_t st_backlash_y;
|
||||||
//!@n M207 - set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting
|
//!@n M207 - set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop], stays in mm regardless of M200 setting
|
||||||
//!@n M208 - set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/sec]
|
//!@n M208 - set recover=unretract length S[positive mm surplus to the M207 S*] F[feedrate mm/sec]
|
||||||
//!@n M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.
|
//!@n M209 - S<1=true/0=false> enable automatic retract detect if the slicer did not support G10/11: every normal extrude-only move will be classified as retract depending on the direction.
|
||||||
|
//!@n M214 - Set Arc Parameters (Use M500 to store in eeprom) P<MM_PER_ARC_SEGMENT> S<MIN_MM_PER_ARC_SEGMENT> R<MIN_ARC_SEGMENTS> F<ARC_SEGMENTS_PER_SEC>
|
||||||
//!@n M218 - set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>
|
//!@n M218 - set hotend offset (in mm): T<extruder_number> X<offset_on_X> Y<offset_on_Y>
|
||||||
//!@n M220 S<factor in percent>- set speed factor override percentage
|
//!@n M220 S<factor in percent>- set speed factor override percentage
|
||||||
//!@n M221 S<factor in percent>- set extrude factor override percentage
|
//!@n M221 S<factor in percent>- set extrude factor override percentage
|
||||||
|
@ -4900,6 +4901,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
|
||||||
#### Parameters
|
#### Parameters
|
||||||
- `X` - The position to move to on the X axis
|
- `X` - The position to move to on the X axis
|
||||||
- `Y` - The position to move to on the Y axis
|
- `Y` - The position to move to on the Y axis
|
||||||
|
- 'Z' - The position to move to on the Z axis
|
||||||
- `I` - The point in X space from the current X position to maintain a constant distance from
|
- `I` - The point in X space from the current X position to maintain a constant distance from
|
||||||
- `J` - The point in Y space from the current Y position to maintain a constant distance from
|
- `J` - The point in Y space from the current Y position to maintain a constant distance from
|
||||||
- `E` - The amount to extrude between the starting point and ending point
|
- `E` - The amount to extrude between the starting point and ending point
|
||||||
|
@ -7502,9 +7504,46 @@ Sigma_Exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
}break;
|
}break;
|
||||||
#endif // FWRETRACT
|
#endif // FWRETRACT
|
||||||
|
/*!
|
||||||
|
### M214 - Set Arc configuration values (Use M500 to store in eeprom)
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
M214 [P] [S] [N] [R] [F]
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
- `P` - A float representing the max and default millimeters per arc segment. Must be greater than 0.
|
||||||
|
- `S` - A float representing the minimum allowable millimeters per arc segment. Set to 0 to disable
|
||||||
|
- `N` - An int representing the number of arcs to draw before correcting the small angle approximation. Set to 0 to disable.
|
||||||
|
- `R` - An int representing the minimum number of segments per arcs of any radius,
|
||||||
|
except when the results in segment lengths greater than or less than the minimum
|
||||||
|
and maximum segment length. Set to 0 to disable.
|
||||||
|
- 'F' - An int representing the number of segments per second, unless this results in segment lengths
|
||||||
|
greater than or less than the minimum and maximum segment length. Set to 0 to disable.
|
||||||
|
*/
|
||||||
|
case 214: //!@n M214 - Set Arc Parameters (Use M500 to store in eeprom) P<MM_PER_ARC_SEGMENT> S<MIN_MM_PER_ARC_SEGMENT> R<MIN_ARC_SEGMENTS> F<ARC_SEGMENTS_PER_SEC>
|
||||||
|
{
|
||||||
|
// Extract all possible parameters if they appear
|
||||||
|
float p = code_seen('P') ? code_value_float() : cs.mm_per_arc_segment;
|
||||||
|
float s = code_seen('S') ? code_value_float() : cs.min_mm_per_arc_segment;
|
||||||
|
unsigned char n = code_seen('N') ? code_value() : cs.n_arc_correction;
|
||||||
|
unsigned short r = code_seen('R') ? code_value() : cs.min_arc_segments;
|
||||||
|
unsigned short f = code_seen('F') ? code_value() : cs.arc_segments_per_sec;
|
||||||
|
|
||||||
|
// Ensure mm_per_arc_segment is greater than 0, and that min_mm_per_arc_segment is sero or greater than or equal to mm_per_arc_segment
|
||||||
|
if (p <=0 || s < 0 || p < s)
|
||||||
|
{
|
||||||
|
// Should we display some error here?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.mm_per_arc_segment = p;
|
||||||
|
cs.min_mm_per_arc_segment = s;
|
||||||
|
cs.n_arc_correction = n;
|
||||||
|
cs.min_arc_segments = r;
|
||||||
|
cs.arc_segments_per_sec = f;
|
||||||
|
}break;
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -9643,15 +9682,12 @@ void prepare_move()
|
||||||
|
|
||||||
void prepare_arc_move(bool isclockwise) {
|
void prepare_arc_move(bool isclockwise) {
|
||||||
float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc
|
float r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for mc_arc
|
||||||
|
|
||||||
// Trace the arc
|
// Trace the arc
|
||||||
mc_arc(current_position, destination, offset, X_AXIS, Y_AXIS, Z_AXIS, feedrate*feedmultiply/60/100.0, r, isclockwise, active_extruder);
|
mc_arc(current_position, destination, offset, feedrate * feedmultiply / 60 / 100.0, r, isclockwise, active_extruder);
|
||||||
|
|
||||||
// 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
|
||||||
// in any intermediate location.
|
// in any intermediate location.
|
||||||
set_current_to_destination();
|
set_current_to_destination();
|
||||||
|
|
||||||
previous_millis_cmd.start();
|
previous_millis_cmd.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||||
Copyright (c) 2011 Sungeun K. Jeon
|
Copyright (c) 2011 Sungeun K. Jeon
|
||||||
|
Copyright (c) 2020 Brad Hochgesang
|
||||||
|
|
||||||
Grbl is free software: you can redistribute it and/or modify
|
Grbl is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,47 +26,69 @@
|
||||||
|
|
||||||
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
||||||
// segment is configured in settings.mm_per_arc_segment.
|
// segment is configured in settings.mm_per_arc_segment.
|
||||||
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
|
void mc_arc(float* position, float* target, float* offset, float feed_rate, float radius, bool isclockwise, uint8_t extruder)
|
||||||
uint8_t axis_linear, float feed_rate, float radius, bool isclockwise, uint8_t extruder)
|
|
||||||
{
|
{
|
||||||
// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
|
float r_axis_x = -offset[X_AXIS]; // Radius vector from center to current location
|
||||||
// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc
|
float r_axis_y = -offset[Y_AXIS];
|
||||||
float center_axis0 = position[axis_0] + offset[axis_0];
|
float center_axis_x = position[X_AXIS] - r_axis_x;
|
||||||
float center_axis1 = position[axis_1] + offset[axis_1];
|
float center_axis_y = position[Y_AXIS] - r_axis_y;
|
||||||
float linear_travel = target[axis_linear] - position[axis_linear];
|
float travel_z = target[Z_AXIS] - position[Z_AXIS];
|
||||||
float extruder_travel = target[E_AXIS] - position[E_AXIS];
|
float rt_x = target[X_AXIS] - center_axis_x;
|
||||||
float r_axis0 = -offset[axis_0]; // Radius vector from center to current location
|
float rt_y = target[Y_AXIS] - center_axis_y;
|
||||||
float r_axis1 = -offset[axis_1];
|
// 20200419 - Add a variable that will be used to hold the arc segment length
|
||||||
float rt_axis0 = target[axis_0] - center_axis0;
|
float mm_per_arc_segment = cs.mm_per_arc_segment;
|
||||||
float rt_axis1 = target[axis_1] - center_axis1;
|
// 20210109 - Add a variable to hold the n_arc_correction value
|
||||||
|
unsigned char n_arc_correction = cs.n_arc_correction;
|
||||||
|
|
||||||
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
||||||
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
|
float angular_travel_total = atan2(r_axis_x * rt_y - r_axis_y * rt_x, r_axis_x * rt_x + r_axis_y * rt_y);
|
||||||
if (angular_travel < 0) { angular_travel += 2*M_PI; }
|
if (angular_travel_total < 0) { angular_travel_total += 2 * M_PI; }
|
||||||
if (isclockwise) { angular_travel -= 2*M_PI; }
|
|
||||||
|
if (cs.min_arc_segments > 0)
|
||||||
|
{
|
||||||
|
// 20200417 - FormerLurker - Implement MIN_ARC_SEGMENTS if it is defined - from Marlin 2.0 implementation
|
||||||
|
// Do this before converting the angular travel for clockwise rotation
|
||||||
|
mm_per_arc_segment = radius * ((2.0f * M_PI) / cs.min_arc_segments);
|
||||||
|
}
|
||||||
|
if (cs.arc_segments_per_sec > 0)
|
||||||
|
{
|
||||||
|
// 20200417 - FormerLurker - Implement MIN_ARC_SEGMENTS if it is defined - from Marlin 2.0 implementation
|
||||||
|
float mm_per_arc_segment_sec = (feed_rate / 60.0f) * (1.0f / cs.arc_segments_per_sec);
|
||||||
|
if (mm_per_arc_segment_sec < mm_per_arc_segment)
|
||||||
|
mm_per_arc_segment = mm_per_arc_segment_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: no need to check to see if min_mm_per_arc_segment is enabled or not (i.e. = 0), since mm_per_arc_segment can never be below 0.
|
||||||
|
if (mm_per_arc_segment < cs.min_mm_per_arc_segment)
|
||||||
|
{
|
||||||
|
// 20200417 - FormerLurker - Implement MIN_MM_PER_ARC_SEGMENT if it is defined
|
||||||
|
// This prevents a very high number of segments from being generated for curves of a short radius
|
||||||
|
mm_per_arc_segment = cs.min_mm_per_arc_segment;
|
||||||
|
}
|
||||||
|
else if (mm_per_arc_segment > cs.mm_per_arc_segment) {
|
||||||
|
// 20210113 - This can be implemented in an else if since we can't be below the min AND above the max at the same time.
|
||||||
|
// 20200417 - FormerLurker - Implement MIN_MM_PER_ARC_SEGMENT if it is defined
|
||||||
|
mm_per_arc_segment = cs.mm_per_arc_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the angular travel if the direction is clockwise
|
||||||
|
if (isclockwise) { angular_travel_total -= 2 * M_PI; }
|
||||||
|
|
||||||
//20141002:full circle for G03 did not work, e.g. G03 X80 Y80 I20 J0 F2000 is giving an Angle of zero so head is not moving
|
//20141002:full circle for G03 did not work, e.g. G03 X80 Y80 I20 J0 F2000 is giving an Angle of zero so head is not moving
|
||||||
//to compensate when start pos = target pos && angle is zero -> angle = 2Pi
|
//to compensate when start pos = target pos && angle is zero -> angle = 2Pi
|
||||||
if (position[axis_0] == target[axis_0] && position[axis_1] == target[axis_1] && angular_travel == 0)
|
if (position[X_AXIS] == target[X_AXIS] && position[Y_AXIS] == target[Y_AXIS] && angular_travel_total == 0)
|
||||||
{
|
{
|
||||||
angular_travel += 2*M_PI;
|
angular_travel_total += 2 * M_PI;
|
||||||
}
|
}
|
||||||
//end fix G03
|
//end fix G03
|
||||||
|
|
||||||
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
|
// 20200417 - FormerLurker - rename millimeters_of_travel to millimeters_of_travel_arc to better describe what we are
|
||||||
if (millimeters_of_travel < 0.001) { return; }
|
// calculating here
|
||||||
uint16_t segments = floor(millimeters_of_travel/MM_PER_ARC_SEGMENT);
|
const float millimeters_of_travel_arc = hypot(angular_travel_total * radius, fabs(travel_z));
|
||||||
if(segments == 0) segments = 1;
|
if (millimeters_of_travel_arc < 0.001) { return; }
|
||||||
|
|
||||||
/*
|
// Calculate the number of arc segments
|
||||||
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated
|
unsigned short segments = static_cast<unsigned short>(ceil(millimeters_of_travel_arc / mm_per_arc_segment));
|
||||||
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of
|
|
||||||
// all segments.
|
|
||||||
if (invert_feed_rate) { feed_rate *= segments; }
|
|
||||||
*/
|
|
||||||
float theta_per_segment = angular_travel/segments;
|
|
||||||
float linear_per_segment = linear_travel/segments;
|
|
||||||
float extruder_per_segment = extruder_travel/segments;
|
|
||||||
|
|
||||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||||
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
||||||
|
@ -80,66 +103,60 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
|
||||||
round off issues for CNC applications.) Single precision error can accumulate to be greater than
|
round off issues for CNC applications.) Single precision error can accumulate to be greater than
|
||||||
tool precision in some cases. Therefore, arc path correction is implemented.
|
tool precision in some cases. Therefore, arc path correction is implemented.
|
||||||
|
|
||||||
Small angle approximation may be used to reduce computation overhead further. This approximation
|
The small angle approximation was removed because of excessive errors for small circles (perhaps unique to
|
||||||
holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
|
3d printing applications, causing significant path deviation and extrusion issues).
|
||||||
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
|
Now there will be no corrections applied, but an accurate initial sin and cos will be calculated.
|
||||||
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
|
This seems to work with a very high degree of accuracy and results in much simpler code.
|
||||||
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
|
|
||||||
issue for CNC machines with the single precision Arduino calculations.
|
|
||||||
|
|
||||||
This approximation also allows mc_arc to immediately insert a line segment into the planner
|
Finding a faster way to approximate sin, knowing that there can be substantial deviations from the true
|
||||||
without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
|
arc when using the previous approximation, would be beneficial.
|
||||||
a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
|
|
||||||
This is important when there are successive arc motions.
|
|
||||||
*/
|
*/
|
||||||
// Vector rotation matrix values
|
|
||||||
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
|
|
||||||
float sin_T = theta_per_segment;
|
|
||||||
|
|
||||||
float arc_target[4];
|
// If there is only one segment, no need to do a bunch of work since this is a straight line!
|
||||||
float sin_Ti;
|
if (segments > 1)
|
||||||
float cos_Ti;
|
{
|
||||||
float r_axisi;
|
// Calculate theta per segments, and linear (z) travel per segment, e travel per segment
|
||||||
uint16_t i;
|
// as well as the small angle approximation for sin and cos.
|
||||||
int8_t count = 0;
|
const float theta_per_segment = angular_travel_total / segments,
|
||||||
|
linear_per_segment = travel_z / (segments),
|
||||||
// Initialize the linear axis
|
segment_extruder_travel = (target[E_AXIS] - position[E_AXIS]) / (segments),
|
||||||
arc_target[axis_linear] = position[axis_linear];
|
sq_theta_per_segment = theta_per_segment * theta_per_segment,
|
||||||
|
sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6,
|
||||||
// Initialize the extruder axis
|
cos_T = 1 - 0.5f * sq_theta_per_segment;
|
||||||
arc_target[E_AXIS] = position[E_AXIS];
|
// Loop through all but one of the segments. The last one can be done simply
|
||||||
|
// by moving to the target.
|
||||||
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
for (uint16_t i = 1; i < segments; i++) {
|
||||||
|
if (n_arc_correction-- == 0) {
|
||||||
if (count < N_ARC_CORRECTION) {
|
// Calculate the actual position for r_axis_x and r_axis_y
|
||||||
// Apply vector rotation matrix
|
const float cos_Ti = cos(i * theta_per_segment), sin_Ti = sin(i * theta_per_segment);
|
||||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
r_axis_x = -offset[X_AXIS] * cos_Ti + offset[Y_AXIS] * sin_Ti;
|
||||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
r_axis_y = -offset[X_AXIS] * sin_Ti - offset[Y_AXIS] * cos_Ti;
|
||||||
r_axis1 = r_axisi;
|
// reset n_arc_correction
|
||||||
count++;
|
n_arc_correction = cs.n_arc_correction;
|
||||||
} else {
|
}
|
||||||
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
|
else {
|
||||||
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
// Calculate X and Y using the small angle approximation
|
||||||
cos_Ti = cos(i*theta_per_segment);
|
const float r_axisi = r_axis_x * sin_T + r_axis_y * cos_T;
|
||||||
sin_Ti = sin(i*theta_per_segment);
|
r_axis_x = r_axis_x * cos_T - r_axis_y * sin_T;
|
||||||
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
r_axis_y = r_axisi;
|
||||||
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
|
||||||
count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update arc_target location
|
// Update Position
|
||||||
arc_target[axis_0] = center_axis0 + r_axis0;
|
position[X_AXIS] = center_axis_x + r_axis_x;
|
||||||
arc_target[axis_1] = center_axis1 + r_axis1;
|
position[Y_AXIS] = center_axis_y + r_axis_y;
|
||||||
arc_target[axis_linear] += linear_per_segment;
|
position[Z_AXIS] += linear_per_segment;
|
||||||
arc_target[E_AXIS] += extruder_per_segment;
|
position[E_AXIS] += segment_extruder_travel;
|
||||||
|
// Clamp to the calculated position.
|
||||||
clamp_to_software_endstops(arc_target);
|
clamp_to_software_endstops(position);
|
||||||
plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, extruder);
|
// Insert the segment into the buffer
|
||||||
|
plan_buffer_line(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS], feed_rate, extruder, position);
|
||||||
|
// Handle the situation where the planner is aborted hard.
|
||||||
|
if (waiting_inside_plan_buffer_line_print_aborted)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Clamp to the target position.
|
||||||
|
clamp_to_software_endstops(target);
|
||||||
// Ensure last segment arrives at target location.
|
// Ensure last segment arrives at target location.
|
||||||
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder);
|
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, extruder, target);
|
||||||
|
|
||||||
// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
||||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||||
// for vector transformation direction.
|
// for vector transformation direction.
|
||||||
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
|
void mc_arc(float *position, float *target, float *offset, float feed_rate, float radius,
|
||||||
uint8_t axis_linear, float feed_rate, float radius, bool isclockwise, uint8_t extruder);
|
bool isclockwise, uint8_t extruder);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -525,4 +525,16 @@
|
||||||
|
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -529,4 +529,16 @@
|
||||||
//#define HEATBED_ANALYSIS //for meash bed leveling and heatbed analysis D-codes D80 and D81
|
//#define HEATBED_ANALYSIS //for meash bed leveling and heatbed analysis D-codes D80 and D81
|
||||||
//#define MICROMETER_LOGGING //related to D-codes D80 and D81, currently works on MK2.5 only (MK3 board pin definitions missing)
|
//#define MICROMETER_LOGGING //related to D-codes D80 and D81, currently works on MK2.5 only (MK3 board pin definitions missing)
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -532,4 +532,16 @@
|
||||||
//#define MMU_ALWAYS_CUT
|
//#define MMU_ALWAYS_CUT
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -533,4 +533,16 @@
|
||||||
//#define MMU_ALWAYS_CUT
|
//#define MMU_ALWAYS_CUT
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -671,4 +671,16 @@
|
||||||
#define MMU_HAS_CUTTER
|
#define MMU_HAS_CUTTER
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -683,4 +683,16 @@
|
||||||
//#define MMU_ALWAYS_CUT
|
//#define MMU_ALWAYS_CUT
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -449,4 +449,16 @@ THERMISTORS SETTINGS
|
||||||
|
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
|
@ -438,4 +438,16 @@ THERMISTORS SETTINGS
|
||||||
|
|
||||||
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
|
||||||
|
|
||||||
|
// Default Arc Interpolation Settings (Now configurable via M214)
|
||||||
|
#define DEFAULT_N_ARC_CORRECTION 25 // Number of interpolated segments between corrections.
|
||||||
|
/* A value of 1 or less for N_ARC_CORRECTION will trigger the use of Sin and Cos for every arc, which will improve accuracy at the
|
||||||
|
cost of performance*/
|
||||||
|
#define DEFAULT_MM_PER_ARC_SEGMENT 1.0f // REQUIRED - The enforced maximum length of an arc segment
|
||||||
|
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0.5f //the enforced minimum length of an interpolated segment
|
||||||
|
/* MIN_MM_PER_ARC_SEGMENT Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0
|
||||||
|
or ARC_SEGMENTS_PER_SEC > 0 . If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum
|
||||||
|
calculated segment length is used. */
|
||||||
|
#define DEFAULT_MIN_ARC_SEGMENTS 20 // The enforced minimum segments in a full circle of the same radius. Set to 0 to disable
|
||||||
|
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // Use feedrate to choose segment length. Set to 0 to disable
|
||||||
|
|
||||||
#endif //__CONFIGURATION_PRUSA_H
|
#endif //__CONFIGURATION_PRUSA_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue