Skip to content
Permalink
Browse files

Move endstop handling into a time-based procedure.

Before, endstops were checked on every step, wasting precious time.
Checking them 500 times a second should be more than sufficient.

Additionally, an endstop stop now properly decelerates the movement.
This is one important step towards handling accidental endstop hits
gracefully, as it avoids step losses in such situations.
  • Loading branch information...
Traumflug committed Mar 24, 2013
1 parent 5b842e2 commit 0b4e6cb547cb7dbe6dc7f651ba09faa4d2e86484
Showing with 155 additions and 90 deletions.
  1. +132 −90 dda.c
  2. +3 −0 dda.h
  3. +17 −0 dda_queue.c
  4. +1 −0 dda_queue.h
  5. +2 −0 timer.c
222 dda.c
@@ -19,7 +19,7 @@
#include "debug.h"
#include "sersendf.h"
#include "pinio.h"
#include "config.h"
#include "memory_barrier.h"
//#include "graycode.c"

#ifdef DC_EXTRUDER
@@ -461,35 +461,9 @@ void dda_start(DDA *dda) {
Finally we de-assert any asserted step pins.
*/
void dda_step(DDA *dda) {
uint8_t endstop_stop; ///< Stop due to endstop trigger
uint8_t endstop_not_done = 0; ///< Which axes haven't finished homing

#if defined X_MIN_PIN || defined X_MAX_PIN
if (dda->endstop_check & 0x1) {
#if defined X_MIN_PIN
if (x_min() == dda->endstop_stop_cond)
move_state.debounce_count_xmin++;
else
move_state.debounce_count_xmin = 0;
#endif

#if defined X_MAX_PIN
if (x_max() == dda->endstop_stop_cond)
move_state.debounce_count_xmax++;
else
move_state.debounce_count_xmax = 0;
#endif

endstop_stop = move_state.debounce_count_xmin >= ENDSTOP_STEPS ||
move_state.debounce_count_xmax >= ENDSTOP_STEPS;
if (!endstop_stop)
endstop_not_done |= 0x1;
} else
#endif
endstop_stop = 0;

#if ! defined ACCELERATION_TEMPORAL
if ((move_state.x_steps) && ! endstop_stop) {
if (move_state.x_steps) {
move_state.x_counter -= dda->x_delta;
if (move_state.x_counter < 0) {
x_step();
@@ -498,40 +472,16 @@ void dda_step(DDA *dda) {
}
}
#else // ACCELERATION_TEMPORAL
if ((dda->axis_to_step == 'x') && ! endstop_stop) {
if (dda->axis_to_step == 'x') {
x_step();
move_state.x_steps--;
move_state.x_time += dda->x_step_interval;
move_state.all_time = move_state.x_time;
}
#endif

#if defined Y_MIN_PIN || defined Y_MAX_PIN
if (dda->endstop_check & 0x2) {
#if defined Y_MIN_PIN
if (y_min() == dda->endstop_stop_cond)
move_state.debounce_count_ymin++;
else
move_state.debounce_count_ymin = 0;
#endif

#if defined Y_MAX_PIN
if (y_max() == dda->endstop_stop_cond)
move_state.debounce_count_ymax++;
else
move_state.debounce_count_ymax = 0;
#endif

endstop_stop = move_state.debounce_count_ymin >= ENDSTOP_STEPS ||
move_state.debounce_count_ymax >= ENDSTOP_STEPS;
if (!endstop_stop)
endstop_not_done |= 0x2;
} else
#endif
endstop_stop = 0;

#if ! defined ACCELERATION_TEMPORAL
if ((move_state.y_steps) && ! endstop_stop) {
if (move_state.y_steps) {
move_state.y_counter -= dda->y_delta;
if (move_state.y_counter < 0) {
y_step();
@@ -548,32 +498,8 @@ void dda_step(DDA *dda) {
}
#endif

#if defined Z_MIN_PIN || defined Z_MAX_PIN
if (dda->endstop_check & 0x4) {
#if defined Z_MIN_PIN
if (z_min() == dda->endstop_stop_cond)
move_state.debounce_count_zmin++;
else
move_state.debounce_count_zmin = 0;
#endif

#if defined Z_MAX_PIN
if (z_max() == dda->endstop_stop_cond)
move_state.debounce_count_zmax++;
else
move_state.debounce_count_zmax = 0;
#endif

endstop_stop = move_state.debounce_count_zmin >= ENDSTOP_STEPS ||
move_state.debounce_count_zmax >= ENDSTOP_STEPS;
if (!endstop_stop)
endstop_not_done |= 0x4;
} else
#endif
endstop_stop = 0;

#if ! defined ACCELERATION_TEMPORAL
if ((move_state.z_steps) && ! endstop_stop) {
if (move_state.z_steps) {
move_state.z_counter -= dda->z_delta;
if (move_state.z_counter < 0) {
z_step();
@@ -582,7 +508,7 @@ void dda_step(DDA *dda) {
}
}
#else // ACCELERATION_TEMPORAL
if ((dda->axis_to_step == 'z') && ! endstop_stop) {
if (dda->axis_to_step == 'z') {
z_step();
move_state.z_steps--;
move_state.z_time += dda->z_step_interval;
@@ -673,6 +599,17 @@ void dda_step(DDA *dda) {
// move_state.c, move_state.step_no, move_state.y_steps);
}
move_state.step_no++;

#ifdef ACCELERATION_RAMPING
// This is a hack which deals with movements with an unknown number of
// acceleration steps. dda_create() sets a very high number, then.
if (move_state.c < dda->c_min &&
dda->rampup_steps > move_state.step_no + 5) {
dda->rampup_steps = move_state.step_no;
dda->rampdown_steps = dda->total_steps - dda->rampup_steps;
}
#endif

// Print the number of steps actually needed for ramping up
// Needed for comparing the number with the one calculated in dda_create()
//static char printed = 0;
@@ -689,13 +626,6 @@ void dda_step(DDA *dda) {
// move_state.c, dda->c_min, move_state.n);
#endif

// TODO: If we stop axes individually, could we home two or more axes at the same time?
if (dda->endstop_check != 0x0 && endstop_not_done == 0x0) {
move_state.x_steps = move_state.y_steps = move_state.z_steps = move_state.e_steps = 0;
endstops_off();
// as we stop without ramping down, we have to re-init our ramping here
dda_init();
}
#ifdef ACCELERATION_TEMPORAL
/** How is this ACCELERATION TEMPORAL expected to work?
@@ -737,9 +667,10 @@ void dda_step(DDA *dda) {
dda->c <<= 8;
#endif

// If there are no steps left, we have finished.
if (move_state.x_steps == 0 && move_state.y_steps == 0 &&
move_state.z_steps == 0 && move_state.e_steps == 0) {
// If there are no steps left or an endstop stop happened, we have finished.
if ((move_state.x_steps == 0 && move_state.y_steps == 0 &&
move_state.z_steps == 0 && move_state.e_steps == 0) ||
(dda->endstop_check && move_state.n == -3)) {
dda->live = 0;
#ifdef LOOKAHEAD
// If look-ahead was using this move, it could have missed our activation:
@@ -773,6 +704,117 @@ void dda_step(DDA *dda) {
unstep();
}

/*! Do regular movement maintenance.
This should be called pretty often, like once every 1 ot 2 milliseconds.
Currently, this is checking the endstops. These don't need to be checked on
every single step, so this code can be moved out of the highly time critical
dda_step(). At high precision (slow) searches of the endstop, this function
is called more often than dda_step() anyways.
In the future, acceleration and arc movement calculations might go here, too.
Updating speed 500 times a second is easily enough for smooth acceleration!
*/
void dda_clock() {
DDA *dda;
static DDA *last_dda = NULL;
static uint8_t endstop_stop = 0; ///< Stop due to endstop trigger

dda = queue_current_movement();
if (dda != last_dda) {
move_state.debounce_count_xmin = move_state.debounce_count_ymin =
move_state.debounce_count_zmin = move_state.debounce_count_xmax =
move_state.debounce_count_ymax = move_state.debounce_count_zmax = 0;
endstop_stop = 0;
}

if (dda == NULL)
return;

// Caution: we mangle step counters here without locking interrupts. This
// means, we trust dda isn't changed behind our back, which could
// in principle (but rarely) happen if endstops are checked not as
// endstop search, but as part of normal operations.
if (endstop_stop == 0) {
#if defined X_MIN_PIN || defined X_MAX_PIN
if (dda->endstop_check & 0x1) {
#if defined X_MIN_PIN
if (x_min() == dda->endstop_stop_cond)
move_state.debounce_count_xmin++;
else
move_state.debounce_count_xmin = 0;
#endif
#if defined X_MAX_PIN
if (x_max() == dda->endstop_stop_cond)
move_state.debounce_count_xmax++;
else
move_state.debounce_count_xmax = 0;
#endif
endstop_stop = move_state.debounce_count_xmin >= ENDSTOP_STEPS ||
move_state.debounce_count_xmax >= ENDSTOP_STEPS;
}
#endif

#if defined Y_MIN_PIN || defined Y_MAX_PIN
if (dda->endstop_check & 0x2) {
#if defined Y_MIN_PIN
if (y_min() == dda->endstop_stop_cond)
move_state.debounce_count_ymin++;
else
move_state.debounce_count_ymin = 0;
#endif
#if defined Y_MAX_PIN
if (y_max() == dda->endstop_stop_cond)
move_state.debounce_count_ymax++;
else
move_state.debounce_count_ymax = 0;
#endif
endstop_stop = move_state.debounce_count_ymin >= ENDSTOP_STEPS ||
move_state.debounce_count_ymax >= ENDSTOP_STEPS;
}
#endif

#if defined Z_MIN_PIN || defined Z_MAX_PIN
if (dda->endstop_check & 0x4) {
#if defined Z_MIN_PIN
if (z_min() == dda->endstop_stop_cond)
move_state.debounce_count_zmin++;
else
move_state.debounce_count_zmin = 0;
#endif
#if defined Z_MAX_PIN
if (z_max() == dda->endstop_stop_cond)
move_state.debounce_count_zmax++;
else
move_state.debounce_count_zmax = 0;
#endif
endstop_stop = move_state.debounce_count_zmin >= ENDSTOP_STEPS ||
move_state.debounce_count_zmax >= ENDSTOP_STEPS;
}
#endif

// If an endstop is definitely triggered, stop the movement.
if (endstop_stop) {
// For always smooth operations, don't halt apruptly,
// but start deceleration here.
uint8_t save_reg = SREG;
cli();
CLI_SEI_BUG_MEMORY_BARRIER();

dda->rampdown_steps = move_state.step_no;
dda->rampup_steps = 0; // in case we're still accelerating

MEMORY_BARRIER();
SREG = save_reg;

endstops_off();
}
} /* if (endstop_stop == 0) */

last_dda = dda;
}

/// update global current_position struct
void update_current_position() {
DDA *dda = &movebuffer[mb_tail];
3 dda.h
@@ -205,6 +205,9 @@ void dda_start(DDA *dda) __attribute__ ((hot));
// DDA takes one step (called from timer interrupt)
void dda_step(DDA *dda) __attribute__ ((hot));

// regular movement maintenance
void dda_clock(void);

// update current_position
void update_current_position(void);

@@ -59,6 +59,23 @@ uint8_t queue_empty() {
return result;
}

/// Return the current movement, or NULL, if there's no movement going on.
DDA *queue_current_movement() {
uint8_t save_reg = SREG;
cli();
CLI_SEI_BUG_MEMORY_BARRIER();

DDA* current = &movebuffer[mb_tail];

if ( ! current->live || current->waitfor_temp || current->nullmove)
current = NULL;

MEMORY_BARRIER();
SREG = save_reg;

return current;
}

// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
@@ -22,6 +22,7 @@ extern DDA movebuffer[MOVEBUFFER_SIZE];
// queue status methods
uint8_t queue_full(void);
uint8_t queue_empty(void);
DDA *queue_current_movement(void);

// take one step
void queue_step(void);
@@ -57,6 +57,8 @@ ISR(TIMER1_COMPB_vect) {
/*
clock stuff
*/
dda_clock();

clock_counter_10ms += TICK_TIME_MS;
if (clock_counter_10ms >= 10) {
clock_counter_10ms -= 10;

0 comments on commit 0b4e6cb

Please sign in to comment.
You can’t perform that action at this time.