Ensure smooth print moves even with LCD enabled

lcd_update can take so much time that the block buffer gets drained if
there are only short segments. This leads to jerky printer movements for
example in circles and a bad print quality.

This change implements a simple check: Only if the block currently
executed is long enough, run lcd_update.
This also means the printer will not show actual values on the LCD nor
will it respond to buttons pressed. A option that keeps the menu
accessible is also available.
Aditionaly, slow down if a block would be so fast that adding a new
block to the buffer would take more time. In this case, the buffer would
drain until it's empty in worst case.
master
Sebastianv650 10 years ago committed by Scott Lahteine
parent 0be6167f14
commit de89dc9f04

@ -496,6 +496,26 @@
#define BABYSTEP_MULTIPLICATOR 1 //faster movements
#endif
// Enabling ENSURE_SMOOTH_MOVES ensures your printer will never stutter (for example in circles with a short segments). That's done in two steps:
// --1--
// During short segments like in circles, the update of the LCD Display can take so long that the block buffer gets completely drained.
// If that happens, the movement of the printer gets very jerky until a longer segment like a longer straight line allows the buffer
// to be filled again. This small stops also effects print quality in a bad way.
// Enable ENSURE_SMOOTH_MOVES to update the LCD only when there is enough time during a move to do so.
// Note that this means the display will not show actual values during this time and your printer will also not react to buttons
// pressed immediately, except ALWAYS_ALLOW_MENU is also enabled.
// --2--
// No block is allowed to take less time than MIN_BLOCK_TIME. That's the time it takes in the main loop to add a new block to the buffer, checking temps,
// including all interruptions due to interrupts, but without LCD update. If we would allow shorter moves, the buffer would start continously draining.
//#define ENSURE_SMOOTH_MOVES
#if ENABLED(ENSURE_SMOOTH_MOVES)
//#define ALWAYS_ALLOW_MENU // If enabled, the menu will be always accessible.
// WARNING: If the menu is entered or navigated during short moves, the printer will stutter like without ENSURE_SMOOTH_MOVES!
#define LCD_UPDATE_THRESHOLD 170 // Minimum duration in ms of the current segment to allow a LCD update.
// Default value is valid for graphical LCDs like the REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER.
#define MIN_BLOCK_TIME 6 // Minimum duration in ms a single block has to take. You shouldn't need to modify this.
#endif
// @section extruder
// extruder advance constant (s2/mm3)

@ -937,12 +937,24 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
if (segment_time < min_segment_time) {
// buffer is draining, add extra time. The amount of time added increases if the buffer is still emptied more.
inverse_mm_s = 1000000.0 / (segment_time + lround(2 * (min_segment_time - segment_time) / moves_queued));
#ifdef XY_FREQUENCY_LIMIT
#if defined(XY_FREQUENCY_LIMIT) || ENABLED(ENSURE_SMOOTH_MOVES)
segment_time = lround(1000000.0 / inverse_mm_s);
#endif
}
}
#endif
#if ENABLED(ENSURE_SMOOTH_MOVES)
#if DISABLED(SLOWDOWN)
unsigned long segment_time = lround(1000000.0 / inverse_mm_s);
#endif
if (segment_time < (MIN_BLOCK_TIME) * 1000UL) {
// buffer will be draining, set to MIN_BLOCK_TIME.
inverse_mm_s = 1000000.0 / (1000.0 * (MIN_BLOCK_TIME));
segment_time = (MIN_BLOCK_TIME) * 1000UL;
}
block->segment_time = segment_time;
#endif
block->nominal_speed = block->millimeters * inverse_mm_s; // (mm/sec) Always > 0
block->nominal_rate = ceil(block->step_event_count * inverse_mm_s); // (step/sec) Always > 0

@ -123,6 +123,10 @@ typedef struct {
#if ENABLED(BARICUDA)
uint32_t valve_pressure, e_to_p_pressure;
#endif
#if ENABLED(ENSURE_SMOOTH_MOVES)
uint32_t segment_time;
#endif
} block_t;
@ -366,6 +370,17 @@ class Planner {
return NULL;
}
#if ENABLED(ENSURE_SMOOTH_MOVES)
static bool long_move() {
if (blocks_queued()) {
block_t* block = &block_buffer[block_buffer_tail];
return (block->segment_time > (LCD_UPDATE_THRESHOLD * 1000UL));
}
else
return true;
}
#endif
#if ENABLED(AUTOTEMP)
static float autotemp_max;
static float autotemp_min;

@ -2710,15 +2710,24 @@ void lcd_update() {
// We arrive here every ~100ms when idling often enough.
// Instead of tracking the changes simply redraw the Info Screen ~1 time a second.
static int8_t lcd_status_update_delay = 1; // first update one loop delayed
if (
#if ENABLED(ULTIPANEL)
currentScreen == lcd_status_screen &&
#endif
!lcd_status_update_delay--) {
lcd_status_update_delay = 9;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
}
#if ENABLED(ENSURE_SMOOTH_MOVES) && ENABLED(ALWAYS_ALLOW_MENU)
if (planner.long_move()) {
#endif
if (
#if ENABLED(ULTIPANEL)
currentScreen == lcd_status_screen &&
#endif
!lcd_status_update_delay--) {
lcd_status_update_delay = 9;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
}
#if ENABLED(ENSURE_SMOOTH_MOVES) && ENABLED(ALWAYS_ALLOW_MENU)
}
#endif
#if ENABLED(ENSURE_SMOOTH_MOVES) && DISABLED(ALWAYS_ALLOW_MENU)
if (planner.long_move()) {
#endif
if (lcdDrawUpdate) {
switch (lcdDrawUpdate) {
@ -2779,6 +2788,9 @@ void lcd_update() {
break;
}
#if ENABLED(ENSURE_SMOOTH_MOVES) && DISABLED(ALWAYS_ALLOW_MENU)
}
#endif
}
}

Loading…
Cancel
Save