Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -2037,8 +2037,11 @@
//#define FILAMENT_MOTION_SENSOR

#if ENABLED(FILAMENT_MOTION_SENSOR)
//#define FILAMENT_SWITCH_AND_MOTION
//#define FILAMENT_SWITCH_AND_MOTION // Define separate pins below to sense motion
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)

#define FILAMENT_MOTION_DISTANCE_MM 3.0 // (mm) Missing distance required to trigger runout

#define NUM_MOTION_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_MOTION#_PIN for each.
//#define FIL_MOTION1_PIN -1

Expand Down Expand Up @@ -2074,7 +2077,7 @@
//#define FIL_MOTION8_STATE LOW
//#define FIL_MOTION8_PULLUP
//#define FIL_MOTION8_PULLDOWN
#endif
#endif // FILAMENT_SWITCH_AND_MOTION
#endif // FILAMENT_MOTION_SENSOR
#endif // FILAMENT_RUNOUT_DISTANCE_MM
#endif // FILAMENT_RUNOUT_SENSOR
Expand Down
9 changes: 8 additions & 1 deletion Marlin/src/feature/runout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
FilamentMonitor runout;

bool FilamentMonitorBase::enabled = true,
FilamentMonitorBase::filament_ran_out; // = false
FilamentMonitorBase::filament_ran_out; // = false

#if ENABLED(HOST_ACTION_COMMANDS)
bool FilamentMonitorBase::host_handling; // = false
Expand All @@ -51,6 +51,11 @@ bool FilamentMonitorBase::enabled = true,
#if ENABLED(FILAMENT_MOTION_SENSOR)
uint8_t FilamentSensorEncoder::motion_detected;
#endif

#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
bool RunoutResponseDelayed::ignore_motion = false;
constexpr float RunoutResponseDelayed::motion_distance_mm;
#endif
#else
int8_t RunoutResponseDebounced::runout_count[NUM_RUNOUT_SENSORS]; // = 0
#endif
Expand All @@ -72,6 +77,8 @@ bool FilamentMonitorBase::enabled = true,

void event_filament_runout(const uint8_t extruder) {

runout.init_for_restart(false); // Reset and disable

if (did_pause_print) return; // Action already in progress. Purge triggered repeated runout.

#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
Expand Down
77 changes: 58 additions & 19 deletions Marlin/src/feature/runout.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@

#if ENABLED(FILAMENT_MOTION_SENSOR)
#define HAS_FILAMENT_MOTION 1
#endif
#if DISABLED(FILAMENT_MOTION_SENSOR) || ENABLED(FILAMENT_SWITCH_AND_MOTION)
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
#define HAS_FILAMENT_SWITCH 1
#endif
#else
#define HAS_FILAMENT_SWITCH 1
#endif

Expand Down Expand Up @@ -129,6 +131,7 @@ class TFilamentMonitor : public FilamentMonitorBase {

// Handle a block completion. RunoutResponseDelayed uses this to
// add up the length of filament moved while the filament is out.
// Called from ISR context!
static void block_completed(const block_t * const b) {
if (enabled) {
response.block_completed(b);
Expand Down Expand Up @@ -171,6 +174,12 @@ class TFilamentMonitor : public FilamentMonitorBase {
}
}
}

// Reset after a filament runout or upon resuming a job
static void init_for_restart(const bool onoff=true) {
response.init_for_restart(onoff);
}

};

/*************************** FILAMENT PRESENCE SENSORS ***************************/
Expand Down Expand Up @@ -267,6 +276,7 @@ class FilamentSensorBase {
}

public:
// Called from ISR context to indicate a block was completed
static void block_completed(const block_t * const b) {
// If the sensor wheel has moved since the last call to
// this method reset the runout counter for the extruder.
Expand Down Expand Up @@ -303,6 +313,7 @@ class FilamentSensorBase {
}

public:
// Called from ISR context to indicate a block was completed
static void block_completed(const block_t * const) {}

static void run() {
Expand Down Expand Up @@ -332,6 +343,7 @@ class FilamentSensorBase {
TERN_(HAS_FILAMENT_SWITCH, static FilamentSensorSwitch switch_sensor);

public:
// Called from ISR context to indicate a block was completed
static void block_completed(const block_t * const b) {
TERN_(HAS_FILAMENT_MOTION, encoder_sensor.block_completed(b));
TERN_(HAS_FILAMENT_SWITCH, switch_sensor.block_completed(b));
Expand Down Expand Up @@ -362,10 +374,17 @@ class FilamentSensorBase {
class RunoutResponseDelayed {
private:
static countdown_t mm_countdown;
static bool ignore_motion; // Flag to ignore the encoder

public:
static float runout_distance_mm;

#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
static constexpr float motion_distance_mm = FILAMENT_MOTION_DISTANCE_MM;
#endif

static void set_ignore_motion(const bool ignore=true) { ignore_motion = ignore; }

static void reset() {
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i) filament_present(i);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
Expand All @@ -377,24 +396,27 @@ class FilamentSensorBase {
#if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG)
static millis_t t = 0;
const millis_t ms = millis();
if (ELAPSED(ms, t)) {
t = millis() + 1000UL;
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Runout remaining mm: "), mm_countdown.runout[i]);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Motion remaining mm: "), mm_countdown.motion[i]);
#endif
SERIAL_EOL();
}
if (PENDING(ms, t)) return;
t = ms + 1000UL;
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Runout remaining mm: "), mm_countdown.runout[i]);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i)
SERIAL_ECHO(i ? F(", ") : F("Motion remaining mm: "), mm_countdown.motion[i]);
#endif
SERIAL_EOL();
#endif
}

// Get runout status for all presence sensors and motion sensors
static runout_flags_t has_run_out() {
runout_flags_t runout_flags{0};
// Runout based on filament presence
for (uint8_t i = 0; i < NUM_RUNOUT_SENSORS; ++i) if (mm_countdown.runout[i] < 0) runout_flags.set(i);
// Runout based on filament motion
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i) if (mm_countdown.motion[i] < 0) runout_flags.set(i);
if (!ignore_motion)
for (uint8_t i = 0; i < NUM_MOTION_SENSORS; ++i) if (mm_countdown.motion[i] < 0) runout_flags.set(i);
#endif
return runout_flags;
}
Expand All @@ -419,38 +441,51 @@ class FilamentSensorBase {
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
static void filament_motion_present(const uint8_t extruder) {
// Same logic as filament_present
if (mm_countdown.motion[extruder] < runout_distance_mm || did_pause_print) {
mm_countdown.motion[extruder] = runout_distance_mm;
if (mm_countdown.motion[extruder] < motion_distance_mm || did_pause_print) {
mm_countdown.motion[extruder] = motion_distance_mm;
mm_countdown.motion_reset.clear(extruder);
}
else
mm_countdown.motion_reset.set(extruder);
}
#endif

// Called from ISR context to indicate a block was completed
static void block_completed(const block_t * const b) {
const int32_t esteps = b->steps.e;
if (!esteps) return;

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

// Only extrusion moves are examined
const int32_t esteps = b->steps.e;
if (!esteps) 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)];

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

// Apply E distance to motion countdown, reset if flagged
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
if (e < NUM_MOTION_SENSORS) {
if (!ignore_motion && 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
}

// Reset after a filament runout or upon resuming a job
static void init_for_restart(const bool onoff=true) {
UNUSED(onoff);
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
reset();
set_ignore_motion(!onoff);
#endif
}
};

#else // !HAS_FILAMENT_RUNOUT_DISTANCE
Expand Down Expand Up @@ -478,11 +513,15 @@ class FilamentSensorBase {
return runout_flags;
}

// Called from ISR context to indicate a block was completed
static void block_completed(const block_t * const) { }

static void filament_present(const uint8_t extruder) {
runout_count[extruder] = runout_threshold;
}

// Reset after a filament runout or upon resuming a job
static void init_for_restart(const bool=true) { reset(); }
};

#endif // !HAS_FILAMENT_RUNOUT_DISTANCE
Loading