3.0.6 sync

This commit is contained in:
michalprusa 2016-08-11 10:42:53 +02:00
parent 30f0528aba
commit 307d17422d
965 changed files with 503030 additions and 72574 deletions
Firmware

248
Firmware/planner.cpp Executable file → Normal file
View file

@ -74,9 +74,8 @@ unsigned long max_acceleration_units_per_sq_second[NUM_AXIS]; // Use M201 to ove
float minimumfeedrate;
float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX
float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX
float max_xy_jerk; //speed than can be stopped at once, if i understand correctly.
float max_z_jerk;
float max_e_jerk;
// Jerk is a maximum immediate velocity change.
float max_jerk[NUM_AXIS];
float mintravelfeedrate;
unsigned long axis_steps_per_sqr_second[NUM_AXIS];
@ -93,6 +92,7 @@ matrix_3x3 plan_bed_level_matrix = {
long position[NUM_AXIS]; //rescaled from extern when axis_steps_per_unit are changed by gcode
static float previous_speed[NUM_AXIS]; // Speed of previous path line segment
static float previous_nominal_speed; // Nominal speed of previous path line segment
static float previous_safe_speed; // Exit speed limited by a jerk to full halt of a previous last segment.
#ifdef AUTOTEMP
float autotemp_max=250;
@ -279,7 +279,7 @@ void planner_recalculate(const float &safe_final_speed)
tail = block_index;
// Update the number of blocks to process.
n_blocks = (block_buffer_head + BLOCK_BUFFER_SIZE - tail) & (BLOCK_BUFFER_SIZE - 1);
SERIAL_ECHOLNPGM("BLOCK_FLAG_START_FROM_FULL_HALT");
// SERIAL_ECHOLNPGM("START");
break;
}
// If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
@ -459,6 +459,54 @@ void check_axes_activity()
#endif
}
bool waiting_inside_plan_buffer_line_print_aborted = false;
/*
void planner_abort_soft()
{
// Empty the queue.
while (blocks_queued()) plan_discard_current_block();
// Relay to planner wait routine, that the current line shall be canceled.
waiting_inside_plan_buffer_line_print_aborted = true;
//current_position[i]
}
*/
void planner_abort_hard()
{
// Abort the stepper routine and flush the planner queue.
quickStop();
// Now the front-end (the Marlin_main.cpp with its current_position) is out of sync.
// First update the planner's current position in the physical motor steps.
position[X_AXIS] = st_get_position(X_AXIS);
position[Y_AXIS] = st_get_position(Y_AXIS);
position[Z_AXIS] = st_get_position(Z_AXIS);
position[E_AXIS] = st_get_position(E_AXIS);
// Second update the current position of the front end.
current_position[X_AXIS] = st_get_position_mm(X_AXIS);
current_position[Y_AXIS] = st_get_position_mm(Y_AXIS);
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
current_position[E_AXIS] = st_get_position_mm(E_AXIS);
// Apply the mesh bed leveling correction to the Z axis.
#ifdef MESH_BED_LEVELING
if (mbl.active)
current_position[Z_AXIS] -= mbl.get_z(current_position[X_AXIS], current_position[Y_AXIS]);
#endif
// Apply inverse world correction matrix.
machine2world(current_position[X_AXIS], current_position[Y_AXIS]);
memcpy(destination, current_position, sizeof(destination));
// Resets planner junction speeds. Assumes start from rest.
previous_nominal_speed = 0.0;
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
// Relay to planner wait routine, that the current line shall be canceled.
waiting_inside_plan_buffer_line_print_aborted = true;
}
float junction_deviation = 0.1;
// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in
@ -471,12 +519,18 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
// If the buffer is full: good! That means we are well ahead of the robot.
// Rest here until there is room in the buffer.
while(block_buffer_tail == next_buffer_head)
{
manage_heater();
// Vojtech: Don't disable motors inside the planner!
manage_inactivity(false);
lcd_update();
if (block_buffer_tail == next_buffer_head) {
waiting_inside_plan_buffer_line_print_aborted = false;
do {
manage_heater();
// Vojtech: Don't disable motors inside the planner!
manage_inactivity(false);
lcd_update();
} while (block_buffer_tail == next_buffer_head);
if (waiting_inside_plan_buffer_line_print_aborted)
// Inside the lcd_update() routine the print has been aborted.
// Cancel the print, do not plan the current line this routine is waiting on.
return;
}
#ifdef ENABLE_AUTO_BED_LEVELING
@ -878,44 +932,40 @@ Having the real displacement of the head, we can calculate the total movement le
}
#endif
// Start with a safe speed.
//Vojtech: This code tries to limit the initial jerk to half of the maximum jerk value.
//The code is not quite correct. It is pessimistic as it shall limit a projection of the jerk into each axis,
//but when the current code clamps, it clamps as if the movement is done in a single axis only.
float vmax_junction = max_xy_jerk/2.f;
if(fabs(current_speed[Z_AXIS]) > max_z_jerk/2.f)
vmax_junction = min(vmax_junction, max_z_jerk/2.f);
if(fabs(current_speed[E_AXIS]) > max_e_jerk/2.f)
vmax_junction = min(vmax_junction, max_e_jerk/2.f);
vmax_junction = min(vmax_junction, block->nominal_speed);
// Safe speed is the speed, from which the machine may halt to stop immediately.
float safe_speed = vmax_junction;
float safe_speed = block->nominal_speed;
bool limited = false;
for (uint8_t axis = 0; axis < 4; ++ axis) {
float jerk = fabs(current_speed[axis]);
if (jerk > max_jerk[axis]) {
// The actual jerk is lower, if it has been limited by the XY jerk.
if (limited) {
// Spare one division by a following gymnastics:
// Instead of jerk *= safe_speed / block->nominal_speed,
// multiply max_jerk[axis] by the divisor.
jerk *= safe_speed;
float mjerk = max_jerk[axis] * block->nominal_speed;
if (jerk > mjerk) {
safe_speed *= mjerk / jerk;
limited = true;
}
} else {
safe_speed = max_jerk[axis];
limited = true;
}
}
}
// Reset the block flag.
block->flag = 0;
// Initial limit on the segment entry velocity.
float vmax_junction;
//FIXME Vojtech: Why only if at least two lines are planned in the queue?
// Is it because we don't want to tinker with the first buffer line, which
// is likely to be executed by the stepper interrupt routine soon?
if (moves_queued > 1 && previous_nominal_speed > 0.0001f) {
#if 1
float jerk;
{
float dx = current_speed[X_AXIS]-previous_speed[X_AXIS];
float dy = current_speed[Y_AXIS]-previous_speed[Y_AXIS];
jerk = sqrt(dx*dx+dy*dy);
}
float vmax_junction_factor = 1.0;
// if((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) {
vmax_junction = block->nominal_speed;
// }
if (jerk > max_xy_jerk)
vmax_junction_factor = max_xy_jerk/jerk;
jerk = fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]);
if (jerk > max_z_jerk)
vmax_junction_factor = min(vmax_junction_factor, max_z_jerk/jerk);
jerk = fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]);
if (jerk > max_e_jerk)
vmax_junction_factor = min(vmax_junction_factor, max_e_jerk/jerk);
//FIXME Vojtech: Why is this asymmetric in regard to the previous nominal speed and the current nominal speed?
vmax_junction = min(previous_nominal_speed, vmax_junction * vmax_junction_factor); // Limit speed to max previous speed
#else
// Estimate a maximum velocity allowed at a joint of two successive segments.
// If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
// then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
@ -926,72 +976,54 @@ Having the real displacement of the head, we can calculate the total movement le
// Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
vmax_junction = prev_speed_larger ? block->nominal_speed : previous_nominal_speed;
// Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
float v_factor_exit = prev_speed_larger ? smaller_speed_factor : 1.f;
float v_factor_entry = prev_speed_larger ? 1.f : smaller_speed_factor;
// First limit the jerk in the XY plane.
float jerk;
{
// Estimate the jerk as if the entry / exit velocity of the two successive segment was limited to the minimum of their nominal velocities.
// If coasting, then the segment transition velocity will define the exit / entry velocities of the successive segments
// and the jerk defined by the following formula will be always lower.
float dx = prev_speed_larger ? (current_speed[X_AXIS] - smaller_speed_factor * previous_speed[X_AXIS]) : (smaller_speed_factor * current_speed[X_AXIS] - previous_speed[X_AXIS]);
float dy = prev_speed_larger ? (current_speed[Y_AXIS] - smaller_speed_factor * previous_speed[Y_AXIS]) : (smaller_speed_factor * current_speed[Y_AXIS] - previous_speed[Y_AXIS]);
jerk = sqrt(dx*dx+dy*dy);
}
if (jerk > max_xy_jerk) {
// Limit the entry / exit velocities to respect the XY jerk limits.
v_factor_exit = v_factor_entry = max_xy_jerk / jerk;
float v_factor = 1.f;
limited = false;
// Now limit the jerk in all axes.
for (uint8_t axis = 0; axis < 4; ++ axis) {
// Limit an axis. We have to differentiate coasting from the reversal of an axis movement, or a full stop.
float v_exit = previous_speed[axis];
float v_entry = current_speed [axis];
if (prev_speed_larger)
v_factor_exit *= smaller_speed_factor;
else
v_factor_entry *= smaller_speed_factor;
v_exit *= smaller_speed_factor;
if (limited) {
v_exit *= v_factor;
v_entry *= v_factor;
}
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
float jerk =
(v_exit > v_entry) ?
((v_entry > 0.f || v_exit < 0.f) ?
// coasting
(v_exit - v_entry) :
// axis reversal
max(v_exit, - v_entry)) :
// v_exit <= v_entry
((v_entry < 0.f || v_exit > 0.f) ?
// coasting
(v_entry - v_exit) :
// axis reversal
max(- v_exit, v_entry));
if (jerk > max_jerk[axis]) {
v_factor *= max_jerk[axis] / jerk;
limited = true;
}
}
// Now limit the Z and E axes. We have to differentiate coasting from the reversal of an axis movement, or a full stop.
float v_exit = previous_speed[Z_AXIS] * v_factor_exit;
float v_entry = current_speed [Z_AXIS] * v_factor_entry;
jerk = (v_exit > v_entry) ?
((v_entry > 0.f || v_exit < 0.f) ?
// coasting
(v_exit - v_entry) :
// axis reversal
max(v_exit, - v_entry)) :
// v_exit <= v_entry
((v_entry < 0.f || v_exit > 0.f) ?
// coasting
(v_entry - v_exit) :
// axis reversal
max(- v_exit, v_entry));
if (jerk > max_z_jerk / 2.f) {
float c = (max_z_jerk / 2.f) / jerk;
v_factor_exit *= c;
v_factor_entry *= c;
if (limited)
vmax_junction *= v_factor;
// Now the transition velocity is known, which maximizes the shared exit / entry velocity while
// respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
float vmax_junction_threshold = vmax_junction * 0.99f;
if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold) {
// Not coasting. The machine will stop and start the movements anyway,
// better to start the segment from start.
block->flag |= BLOCK_FLAG_START_FROM_FULL_HALT;
vmax_junction = safe_speed;
}
// Limit the E axis.
v_exit = previous_speed[E_AXIS] * v_factor_exit;
v_entry = current_speed [E_AXIS] * v_factor_entry;
jerk = (v_exit > v_entry) ?
((v_entry > 0.f || v_exit < 0.f) ?
// coasting
(v_exit - v_entry) :
// axis reversal
max(v_exit, - v_entry)) :
// v_exit <= v_entry
((v_entry < 0.f || v_exit > 0.f) ?
// coasting
(v_entry - v_exit) :
// axis reversal
max(- v_exit, v_entry));
if (jerk > max_e_jerk / 2.f) {
float c = (max_e_jerk / 2.f) / jerk;
v_factor_exit *= c;
v_factor_entry *= c;
}
// Now the transition velocity is known as nominal * v_factor. Compare the transition velocity against the "safe" velocoties.
// If the transition velocity is below the exit / enter safe velocity, the machine is no more cruising, therefore
// the safe velocities shall be used.
#endif
} else {
block->flag |= BLOCK_FLAG_START_FROM_FULL_HALT;
vmax_junction = safe_speed;
}
// Max entry speed of this block equals the max exit speed of the previous block.
block->max_entry_speed = vmax_junction;
@ -1008,12 +1040,12 @@ Having the real displacement of the head, we can calculate the total movement le
// the reverse and forward planners, the corresponding block junction speed will always be at the
// the maximum junction speed and may always be ignored for any speed reduction checks.
// Always calculate trapezoid for new block
block->flag = (block->nominal_speed <= v_allowable) ? (BLOCK_FLAG_NOMINAL_LENGTH | BLOCK_FLAG_RECALCULATE) : BLOCK_FLAG_RECALCULATE;
block->flag |= (block->nominal_speed <= v_allowable) ? (BLOCK_FLAG_NOMINAL_LENGTH | BLOCK_FLAG_RECALCULATE) : BLOCK_FLAG_RECALCULATE;
// Update previous path unit_vector and nominal speed
memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[]
previous_nominal_speed = block->nominal_speed;
previous_safe_speed = safe_speed;
#ifdef ADVANCE
// Calculate advance rate
@ -1056,6 +1088,10 @@ Having the real displacement of the head, we can calculate the total movement le
// interfere with the process.
planner_recalculate(safe_speed);
// SERIAL_ECHOPGM("Q");
// SERIAL_ECHO(int(moves_planned()));
// SERIAL_ECHOLNPGM("");
st_wake_up();
}