Skip to content

Separate endstop and motion sensor thresholds in filament runout detection#27812

Merged
thinkyhead merged 10 commits intoMarlinFirmware:bugfix-2.1.xfrom
MrKuskov:patch-1
May 4, 2025
Merged

Separate endstop and motion sensor thresholds in filament runout detection#27812
thinkyhead merged 10 commits intoMarlinFirmware:bugfix-2.1.xfrom
MrKuskov:patch-1

Conversation

@MrKuskov
Copy link
Contributor

Description

This PR introduces improvements to filament runout detection logic when both endstop switch and motion sensor (encoder) are enabled (FILAMENT_SWITCH_AND_MOTION). Key changes:

  • New ignore_motion flag: Temporarily disables motion sensor checks during endstop-triggered runout events to prevent false positives.

    • Controlled via RunoutResponseDelayed::set_ignore_motion().
    • Automatically reset on print start via new handle_runout_on_print_start().
  • Separate trigger thresholds:

    • Motion sensor now uses dedicated motion_distance_mm (default: FILAMENT_MOTION_DISTANCE_MM), decoupling it from endstop sensitivity.
  • Critical fixes:

    • Motion sensor counters now respect ignore_motion during extrusion.
    • Fixed incorrect usage of runout_distance_mm for motion sensors (now uses motion_distance_mm).
    • Added motion counter reset during runout events to avoid false triggers after recovery.

Requirements

  • Configuration: Only affects setups with FILAMENT_SWITCH_AND_MOTION enabled.
  • Testing: Requires hardware with both endstop and encoder-based filament sensors.

Benefits

  • Prevents false runouts: Motion sensor ignores extrusion movements after endstop triggers.
  • Flexible tuning: Independent distance thresholds for switch vs. encoder.
  • Robust recovery: Clean state reset when starting new prints.

Configurations

Test with:

  • FILAMENT_SWITCH_AND_MOTION enabled
  • Customizable via:
    #define FILAMENT_RUNOUT_DISTANCE_MM 300  // Distance from sensor to extruder (mm)
    #define FILAMENT_RUNOUT_SENSOR_DEBUG    // Enable sensor debugging
    
    #if ENABLED(FILAMENT_MOTION_SENSOR)
      #define FILAMENT_SWITCH_AND_MOTION
      #if ENABLED(FILAMENT_SWITCH_AND_MOTION)
        // Encoder resolution (mm per pulse):
        #ifndef FILAMENT_MOTION_DISTANCE_MM
          #define FILAMENT_MOTION_DISTANCE_MM 3.0  // Default for 20mm encoder wheel
        #endif
    
      // Hardware configuration:
      #define NUM_MOTION_SENSORS 1       // Sensors count (1 per extruder)
      #define FIL_MOTION1_PIN P1_25       // E1DET pin (BTT SKR specific)
    #endif

#endif

@thinkyhead
Copy link
Member

The added function handle_runout_on_print_start() is not called at any point in the code. It may be a little tricky to do so, since there is not always a clear definition about what constitutes a "print start" — but generally any time an SD print is started or resumed from a pause, or if a host that is sending commands sends the command to start the print job timer, that is when you might call handle_runout_on_print_start(). We'll formalize more events like this in the next phase of Marlin after the release of 2.1.3.

The name handle_runout_on_print_start implies that the function will deal with the situation where filament is missing at the beginning of a print job. However, all it does is reset and enable RunoutResponseDelayed, which is a relatively generic behavior. So I have moved it to a method in TFilamentMonitor::init_for_restart(bool onoff=true) indicating it should be called at any point where filament runout detection ought to reset and continue (or to reset and stop).

thinkyhead added a commit to MarlinFirmware/Configurations that referenced this pull request Apr 22, 2025
@thinkyhead
Copy link
Member

I think this is about as complete as it's going to get, but please confirm that the modified code works, particularly the code calling runout.init_for_restart(...) because that is entirely speculative and maybe it does more than it should for the use-case. Once we have that little detail sorted out it should be good to go.

Overall this is a good addition to make more sense of a "motion sensor" as a way to gauge that filament has run out, separating it from the post-runout length, as the intent is not to throw the "M600" alarm until the complete length of filament specified by FILAMENT_RUNOUT_DISTANCE_MM has elapsed, even though the abstract "runout" state of the sensor is triggered.

There are bound to be questions about use-cases for different combinations of runout/motion sensors, so it could help to add more examples to the Filament Runout Sensors page on the Marlin website.

@thinkyhead thinkyhead merged commit 1f31027 into MarlinFirmware:bugfix-2.1.x May 4, 2025
66 checks passed
@vovodroid
Copy link
Contributor

vovodroid commented May 5, 2025

Add new parameter to M412/settings/menu in Configure FILAMENT_SWITCH_AND_MOTION #27836

@vovodroid
Copy link
Contributor

On the other hand, if you set FILAMENT_RUNOUT_DISTANCE_MM larger than FILAMENT_MOTION_DISTANCE_MM (and it could be 200-400mm) no filament jam or slipping will be detected until this length.

EvilGremlin pushed a commit to EvilGremlin/Marlin that referenced this pull request May 15, 2025
rommo911 pushed a commit to rommo911/Marlin-e3v2 that referenced this pull request Sep 16, 2025
@thinkyhead
Copy link
Member

thinkyhead commented Sep 26, 2025

Let's fix the bugs introduced by these changes.

  • The event_filament_runout calls runout.init_for_restart(false) which disables the feature and nothing else ever calls it to re-enable filament detection. This could be a problem.
  • The only thing that ever calls set_ignore_motion —causing motion to be ignored until reboot— is runout.init_for_restart, and it is only ever called in the case of event_filament_runout. Consider where it would make sense to set ignore_motion back to false so that motion detection can resume after a runout event.
  • The FILAMENT_RUNOUT_DISTANCE_MM value is meant to specify how long after a runout event to continue to extrude.
    • If the filament "no motion" sensor has reached its threshold and triggered, yet the "filament out" sensor is not triggered, it indicates a "jam event," not a "runout event." We should report it as a "jam" when going to "wait for filament change."
    • If the "filament motion" sensor is triggered, in all cases, it should skip the FILAMENT_RUNOUT_DISTANCE_MM check because FILAMENT_RUNOUT_DISTANCE_MM is intended for a runout sensor positioned farther than FILAMENT_RUNOUT_DISTANCE_MM ahead of the extruder gear, and if the filament isn't moving at all then there's no point in waiting the extra distance.
  • According to [BUG] Filament runout detection doesn't work after #27812 #27843 FILAMENT_SWITCH_AND_MOTION is just plain broken, most likely due to one or more of the factors listed above.

@thinkyhead
Copy link
Member

With commit b723e3f the ignore_motion flag is now restored on runout.reset() after it was disabled by event_filament_runout. The runout.reset() method is called at the end of the resume_print(...) function so this should cause the motion sensor to resume monitoring once a runout has been resolved.

@vovodroid
Copy link
Contributor

Now on filament runout it triggers after FILAMENT_MOTION_DISTANCE_MM distance (3.6 mm), but non after 380:

#define FILAMENT_RUNOUT_DISTANCE_MM 380

  #ifdef FILAMENT_RUNOUT_DISTANCE_MM
    // Enable this option to use an encoder disc that toggles the runout pin
    // as the filament moves. (Be sure to set FILAMENT_RUNOUT_DISTANCE_MM
    // large enough to avoid false positives.)
    #define FILAMENT_MOTION_SENSOR

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

        #define FILAMENT_MOTION_DISTANCE_MM 3.6 // (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    PC2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants