Support for distinct E factors

This commit is contained in:
Scott Lahteine
2016-12-03 22:02:27 -06:00
parent 0dfe95eaba
commit 3391c785c6
28 changed files with 400 additions and 117 deletions

View File

@ -81,12 +81,16 @@ block_t Planner::block_buffer[BLOCK_BUFFER_SIZE];
volatile uint8_t Planner::block_buffer_head = 0, // Index of the next block to be pushed
Planner::block_buffer_tail = 0;
float Planner::max_feedrate_mm_s[NUM_AXIS], // Max speeds in mm per second
Planner::axis_steps_per_mm[NUM_AXIS],
Planner::steps_to_mm[NUM_AXIS];
float Planner::max_feedrate_mm_s[XYZE_N], // Max speeds in mm per second
Planner::axis_steps_per_mm[XYZE_N],
Planner::steps_to_mm[XYZE_N];
uint32_t Planner::max_acceleration_steps_per_s2[NUM_AXIS],
Planner::max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software
#if ENABLED(DISTINCT_E_FACTORS)
uint8_t Planner::last_extruder = 0; // Respond to extruder change
#endif
uint32_t Planner::max_acceleration_steps_per_s2[XYZE_N],
Planner::max_acceleration_mm_per_s2[XYZE_N]; // Use M201 to override by software
millis_t Planner::min_segment_time;
float Planner::min_feedrate_mm_s,
@ -650,9 +654,17 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
lround(a * axis_steps_per_mm[X_AXIS]),
lround(b * axis_steps_per_mm[Y_AXIS]),
lround(c * axis_steps_per_mm[Z_AXIS]),
lround(e * axis_steps_per_mm[E_AXIS])
lround(e * axis_steps_per_mm[E_AXIS_N])
};
// When changing extruders recalculate steps corresponding to the E position
#if ENABLED(DISTINCT_E_FACTORS)
if (last_extruder != extruder && axis_steps_per_mm[E_AXIS_N] != axis_steps_per_mm[E_AXIS + last_extruder]) {
position[E_AXIS] = lround(position[E_AXIS] * axis_steps_per_mm[E_AXIS_N] * steps_to_mm[E_AXIS + last_extruder]);
last_extruder = extruder;
}
#endif
#if ENABLED(LIN_ADVANCE)
float target_float[XYZE] = {a, b, c, e};
float de_float = target_float[E_AXIS] - position_float[E_AXIS];
@ -702,7 +714,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
if (labs(de) > (int32_t)axis_steps_per_mm[E_AXIS] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int
if (labs(de) > (int32_t)axis_steps_per_mm[E_AXIS_N] * (EXTRUDE_MAXLENGTH)) { // It's not important to get max. extrusion length in a precision < 1mm, so save some cycles and cast to int
position[E_AXIS] = target[E_AXIS]; // Behave as if the move really took place, but ignore E part
de = 0; // no difference
SERIAL_ECHO_START;
@ -941,7 +953,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
delta_mm[Y_AXIS] = db * steps_to_mm[Y_AXIS];
delta_mm[Z_AXIS] = dc * steps_to_mm[Z_AXIS];
#endif
delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS];
delta_mm[E_AXIS] = esteps_float * steps_to_mm[E_AXIS_N];
if (block->steps[X_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[Y_AXIS] < MIN_STEPS_PER_SEGMENT && block->steps[Z_AXIS] < MIN_STEPS_PER_SEGMENT) {
block->millimeters = fabs(delta_mm[E_AXIS]);
@ -1091,16 +1103,16 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
accel = ceil(retract_acceleration * steps_per_mm);
}
else {
#define LIMIT_ACCEL_LONG(AXIS) do{ \
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS] < accel) { \
const uint32_t comp = max_acceleration_steps_per_s2[AXIS] * block->step_event_count; \
#define LIMIT_ACCEL_LONG(AXIS,INDX) do{ \
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \
const uint32_t comp = max_acceleration_steps_per_s2[AXIS+INDX] * block->step_event_count; \
if (accel * block->steps[AXIS] > comp) accel = comp / block->steps[AXIS]; \
} \
}while(0)
#define LIMIT_ACCEL_FLOAT(AXIS) do{ \
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS] < accel) { \
const float comp = (float)max_acceleration_steps_per_s2[AXIS] * (float)block->step_event_count; \
#define LIMIT_ACCEL_FLOAT(AXIS,INDX) do{ \
if (block->steps[AXIS] && max_acceleration_steps_per_s2[AXIS+INDX] < accel) { \
const float comp = (float)max_acceleration_steps_per_s2[AXIS+INDX] * (float)block->step_event_count; \
if ((float)accel * (float)block->steps[AXIS] > comp) accel = comp / (float)block->steps[AXIS]; \
} \
}while(0)
@ -1109,16 +1121,17 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
accel = ceil((esteps ? acceleration : travel_acceleration) * steps_per_mm);
// Limit acceleration per axis
if (block->step_event_count <= cutoff_long){
LIMIT_ACCEL_LONG(X_AXIS);
LIMIT_ACCEL_LONG(Y_AXIS);
LIMIT_ACCEL_LONG(Z_AXIS);
LIMIT_ACCEL_LONG(E_AXIS);
} else {
LIMIT_ACCEL_FLOAT(X_AXIS);
LIMIT_ACCEL_FLOAT(Y_AXIS);
LIMIT_ACCEL_FLOAT(Z_AXIS);
LIMIT_ACCEL_FLOAT(E_AXIS);
if (block->step_event_count <= cutoff_long) {
LIMIT_ACCEL_LONG(X_AXIS,0);
LIMIT_ACCEL_LONG(Y_AXIS,0);
LIMIT_ACCEL_LONG(Z_AXIS,0);
LIMIT_ACCEL_LONG(E_AXIS,extruder);
}
else {
LIMIT_ACCEL_FLOAT(X_AXIS,0);
LIMIT_ACCEL_FLOAT(Y_AXIS,0);
LIMIT_ACCEL_FLOAT(Z_AXIS,0);
LIMIT_ACCEL_FLOAT(E_AXIS,extruder);
}
}
block->acceleration_steps_per_s2 = accel;
@ -1302,7 +1315,7 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
}
else {
block->use_advance_lead = true;
block->abs_adv_steps_multiplier8 = lround(extruder_advance_k * (de_float / mm_D_float) * block->nominal_speed / (float)block->nominal_rate * axis_steps_per_mm[E_AXIS] * 256.0);
block->abs_adv_steps_multiplier8 = lround(extruder_advance_k * (de_float / mm_D_float) * block->nominal_speed / (float)block->nominal_rate * axis_steps_per_mm[E_AXIS_N] * 256.0);
}
#elif ENABLED(ADVANCE)
@ -1350,13 +1363,18 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
*/
void Planner::_set_position_mm(const float &a, const float &b, const float &c, const float &e) {
#if ENABLED(DISTINCT_E_FACTORS)
#define _EINDEX (E_AXIS + active_extruder)
last_extruder = active_extruder;
#else
#define _EINDEX E_AXIS
#endif
long na = position[X_AXIS] = lround(a * axis_steps_per_mm[X_AXIS]),
nb = position[Y_AXIS] = lround(b * axis_steps_per_mm[Y_AXIS]),
nc = position[Z_AXIS] = lround(c * axis_steps_per_mm[Z_AXIS]),
ne = position[E_AXIS] = lround(e * axis_steps_per_mm[E_AXIS]);
ne = position[E_AXIS] = lround(e * axis_steps_per_mm[_EINDEX]);
stepper.set_position(na, nb, nc, ne);
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
ZERO(previous_speed);
}
@ -1386,24 +1404,35 @@ void Planner::sync_from_steppers() {
* Setters for planner position (also setting stepper position).
*/
void Planner::set_position_mm(const AxisEnum axis, const float& v) {
position[axis] = lround(v * axis_steps_per_mm[axis]);
#if ENABLED(DISTINCT_E_FACTORS)
const uint8_t axis_index = axis + (axis == E_AXIS ? active_extruder : 0);
last_extruder = active_extruder;
#else
const uint8_t axis_index = axis;
#endif
position[axis] = lround(v * axis_steps_per_mm[axis_index]);
stepper.set_position(axis, v);
previous_speed[axis] = 0.0;
}
// Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
void Planner::reset_acceleration_rates() {
#if ENABLED(DISTINCT_E_FACTORS)
#define HIGHEST_CONDITION (i < E_AXIS || i == E_AXIS + active_extruder)
#else
#define HIGHEST_CONDITION true
#endif
uint32_t highest_rate = 1;
LOOP_XYZE(i) {
LOOP_XYZE_N(i) {
max_acceleration_steps_per_s2[i] = max_acceleration_mm_per_s2[i] * axis_steps_per_mm[i];
NOLESS(highest_rate, max_acceleration_steps_per_s2[i]);
if (HIGHEST_CONDITION) NOLESS(highest_rate, max_acceleration_steps_per_s2[i]);
}
cutoff_long = 4294967295UL / highest_rate;
}
// Recalculate position, steps_to_mm if axis_steps_per_mm changes!
void Planner::refresh_positioning() {
LOOP_XYZE(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i];
LOOP_XYZE_N(i) steps_to_mm[i] = 1.0 / axis_steps_per_mm[i];
set_position_mm_kinematic(current_position);
reset_acceleration_rates();
}