Skip to content

Commit

Permalink
🐛 Fix runout extra length (MarlinFirmware#26082)
Browse files Browse the repository at this point in the history
Co-authored-by: Scott Lahteine <[email protected]>
Co-authored-by: justvlade <[email protected]>
  • Loading branch information
3 people authored and Pragma8123 committed Jul 28, 2023
1 parent a91346b commit 45eb130
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Marlin/src/feature/runout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bool FilamentMonitorBase::enabled = true,

#if HAS_FILAMENT_RUNOUT_DISTANCE
float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM;
volatile countdown_t RunoutResponseDelayed::mm_countdown;
countdown_t RunoutResponseDelayed::mm_countdown;
#if ENABLED(FILAMENT_MOTION_SENSOR)
uint8_t FilamentSensorEncoder::motion_detected;
#endif
Expand Down
70 changes: 55 additions & 15 deletions Marlin/src/feature/runout.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
#include "../module/planner.h"
#include "../module/stepper.h" // for block_t
#include "../gcode/queue.h"
#include "../feature/pause.h"
#include "../feature/pause.h" // for did_pause_print
#include "../MarlinCore.h" // for printingIsActive()

#include "../inc/MarlinConfig.h"

Expand All @@ -50,9 +51,16 @@
#define HAS_FILAMENT_SWITCH 1
#endif

typedef Flags<8> runout_flags_t;
typedef Flags<
#if NUM_MOTION_SENSORS > NUM_RUNOUT_SENSORS
NUM_MOTION_SENSORS
#else
NUM_RUNOUT_SENSORS
#endif
> runout_flags_t;

void event_filament_runout(const uint8_t extruder);
inline bool should_monitor_runout() { return did_pause_print || printingIsActive(); }

template<class RESPONSE_T, class SENSOR_T>
class TFilamentMonitor;
Expand Down Expand Up @@ -128,7 +136,7 @@ class TFilamentMonitor : public FilamentMonitorBase {

// Give the response a chance to update its counter.
static void run() {
if (enabled && !filament_ran_out && (printingIsActive() || did_pause_print)) {
if (enabled && !filament_ran_out && should_monitor_runout()) {
TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, cli()); // Prevent RunoutResponseDelayed::block_completed from accumulating here
response.run();
sensor.run();
Expand Down Expand Up @@ -340,8 +348,10 @@ class FilamentSensorBase {

typedef struct {
float runout[NUM_RUNOUT_SENSORS];
Flags<NUM_RUNOUT_SENSORS> runout_reset; // Reset runout later
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
float motion[NUM_MOTION_SENSORS];
Flags<NUM_MOTION_SENSORS> motion_reset; // Reset motion later
#endif
} countdown_t;

Expand All @@ -350,7 +360,7 @@ class FilamentSensorBase {
// during a runout condition.
class RunoutResponseDelayed {
private:
static volatile countdown_t mm_countdown;
static countdown_t mm_countdown;

public:
static float runout_distance_mm;
Expand Down Expand Up @@ -389,26 +399,56 @@ class FilamentSensorBase {
}

static void filament_present(const uint8_t extruder) {
mm_countdown.runout[extruder] = runout_distance_mm;
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 leave it in place, or the following unretract will cause runout event.
mm_countdown.runout[extruder] = runout_distance_mm;
mm_countdown.runout_reset.clear(extruder);
}
else {
// If runout is larger than runout distance, we cannot reset right now, as Bowden and retract
// distance larger than runout_distance_mm leads to negative runout right after unretract.
// But we cannot ignore filament_present event. After unretract, runout will become smaller
// than runout_distance_mm and should be reset after that. So activate delayed reset.
mm_countdown.runout_reset.set(extruder);
}
}

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

static void block_completed(const block_t * const b) {
if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state
// Only trigger on extrusion with XYZ movement to allow filament change and retract/recover.
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 ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) mm_countdown.motion[e] -= mm;
#endif
const int32_t esteps = b->steps.e;
if (!esteps) return;

// No calculation unless paused or printing
if (!should_monitor_runout()) return;

// No need to ignore retract/unretract movement since they complement each other
const uint8_t e = b->extruder;
const float mm = (b->direction_bits.e ? esteps : -esteps) * planner.mm_per_step[E_AXIS_N(e)];

if (e < NUM_RUNOUT_SENSORS) {
mm_countdown.runout[e] -= mm;
if (mm_countdown.runout_reset[e]) filament_present(e); // Reset pending. Try to reset.
}

#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) {
mm_countdown.motion[e] -= mm;
if (mm_countdown.motion_reset[e]) filament_motion_present(e); // Reset pending. Try to reset.
}
#endif
}
};

Expand Down

0 comments on commit 45eb130

Please sign in to comment.