Skip to content

Commit

Permalink
Change runout computation algorithm
Browse files Browse the repository at this point in the history
This patch propose idea to take into account retract and unretract motion while computing runout left distance.

Initial idea of fixing issue MarlinFirmware#26061

Unlike patch MarlinFirmware#26082 this code works not only for firmware retract, or classic retract, but also for software wipe retracts, when retract done with horizontal motion.

Modern slicers often introduce new approach to retraction movement. For example Super Slicer allows to enable retraction wipe, which makes retraction during horizontal movement. Also there is an old idea of filament unretract compensation, when unretract is slightly larger then retract movement. Not all printer needed this fix, but if we ignore retract/unretract we will loose those compensation move as well.
  • Loading branch information
justvlade authored Jul 19, 2023
1 parent c462c2d commit ec2f12d
Showing 1 changed file with 28 additions and 8 deletions.
36 changes: 28 additions & 8 deletions Marlin/src/feature/runout.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,10 @@ class FilamentSensorBase {

typedef struct {
float runout[NUM_RUNOUT_SENSORS];
bool runout_reset[NUM_RUNOUT_SENSORS]; // flag to reset runout later if it is not possible to reset now
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
float motion[NUM_MOTION_SENSORS];
bool motion_reset[NUM_MOTION_SENSORS]; // flag to reset motion later if it is not possible to reset now
#endif
} countdown_t;

Expand Down Expand Up @@ -389,32 +391,50 @@ class FilamentSensorBase {
}

static void filament_present(const uint8_t extruder) {
if (mm_countdown.runout[extruder]<runout_distance_mm) {
// reset runout only if it is smaller than runout_distance
if (mm_countdown.runout[extruder]<runout_distance_mm || did_pause_print) {
// reset runout only if it is smaller than runout_distance or printing is paused
// on bowden systems retract may be larger than runout_distance_mm, so if retract was added,
// we should leave it in place, so unretract will not cause runout event
// we should leave it in place, or following unretract will cause runout event
mm_countdown.runout[extruder] = runout_distance_mm;
mm_countdown.runout_reset[extruder] = false; // do not need delayed reset
} else {
// if runout is larger than runout distance, we cannot reset right now, as with bowden and retract distance larger then runout_distance_mm
// it will lead to negative runout right after unretract.
// But we can not ignore filament_present event, as after unretract runout will become smaller then runout_distance_mm
// and it should be resetted after that. So we activate flag to call delayed reset
mm_countdown.runout_reset[extruder] = true;
}
}

#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
static void filament_motion_present(const uint8_t extruder) {
if (mm_countdown.motion[extruder]<runout_distance_mm) {
// same logic as filament_present function
// same logic as filament_present function
if (mm_countdown.motion[extruder]<runout_distance_mm || did_pause_print) {
mm_countdown.motion[extruder] = runout_distance_mm;
mm_countdown.motion_reset[extruder] = false;
} else {
mm_countdown.motion_reset[extruder] = true;
}
}
#endif

static void block_completed(const block_t * const b) {
if (b->steps.e) { // execute calculation if there is any extruder movement
if (b->steps.e && (did_pause_print || printingIsActive())) {
// execute calculation if there is any extruder movement
// and if printer on pause or it is printing
// there is no need to ignore retract/unretract movement as they compensate each other
const uint8_t e = b->extruder;
const int32_t steps = b->steps.e;
const float mm = (b->direction_bits.e ? steps : -steps) * planner.mm_per_step[E_AXIS_N(e)];
if (e < NUM_RUNOUT_SENSORS) mm_countdown.runout[e] -= mm;
if (e < NUM_RUNOUT_SENSORS) {
mm_countdown.runout[e] -= mm;
if (mm_countdown.runout_reset[e]) filament_present(e); // if reset is pending, try to reset
}
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) mm_countdown.motion[e] -= mm;
if (e < NUM_MOTION_SENSORS) {
mm_countdown.motion[e] -= mm;
if (mm_countdown.motion_reset[e]) filament_motion_present(e); // if reset is pending, try to reset
}
#endif
}
}
Expand Down

0 comments on commit ec2f12d

Please sign in to comment.