Browse Source

Rejigger Filament Runout class (#12428)

Scott Lahteine 6 years ago
parent
commit
edfd106bc5
No account linked to committer's email address
4 changed files with 154 additions and 119 deletions
  1. 15
    9
      Marlin/src/feature/runout.cpp
  2. 137
    108
      Marlin/src/feature/runout.h
  3. 1
    1
      Marlin/src/module/stepper.cpp
  4. 1
    1
      Marlin/src/pins/pins.h

+ 15
- 9
Marlin/src/feature/runout.cpp View File

30
 
30
 
31
 #include "runout.h"
31
 #include "runout.h"
32
 
32
 
33
-FilamentRunoutSensor runout;
33
+FilamentMonitor runout;
34
 
34
 
35
-bool FilamentSensorBase::enabled = true,
36
-     FilamentSensorBase::filament_ran_out; // = false
35
+bool FilamentMonitorBase::enabled = true,
36
+     FilamentMonitorBase::filament_ran_out; // = false
37
 
37
 
38
-void FilamentSensorTypeBase::filament_present(const uint8_t extruder) {
39
-  runout.filament_present(extruder);
38
+/**
39
+ * Called by FilamentSensorSwitch::run when filament is detected.
40
+ * Called by FilamentSensorEncoder::block_completed when motion is detected.
41
+ */
42
+void FilamentSensorBase::filament_present(const uint8_t extruder) {
43
+  runout.filament_present(extruder); // calls response.filament_present(extruder)
40
 }
44
 }
41
 
45
 
42
-uint8_t FilamentSensorTypeEncoder::motion_detected,
43
-        FilamentSensorTypeEncoder::old_state; // = 0
46
+#if ENABLED(FILAMENT_MOTION_SENSOR)
47
+  uint8_t FilamentSensorEncoder::motion_detected,
48
+          FilamentSensorEncoder::old_state; // = 0
49
+#endif
44
 
50
 
45
 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
51
 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
46
   float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM;
52
   float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM;
47
-  int32_t RunoutResponseDelayed::steps_since_detection[EXTRUDERS];
53
+  volatile float RunoutResponseDelayed::runout_mm_countdown[EXTRUDERS];
48
 #else
54
 #else
49
-  uint8_t RunoutResponseDebounced::runout_count; // = 0
55
+  int8_t RunoutResponseDebounced::runout_count; // = 0
50
 #endif
56
 #endif
51
 
57
 
52
 #endif // FILAMENT_RUNOUT_SENSOR
58
 #endif // FILAMENT_RUNOUT_SENSOR

+ 137
- 108
Marlin/src/feature/runout.h View File

38
 
38
 
39
 //#define FILAMENT_RUNOUT_SENSOR_DEBUG
39
 //#define FILAMENT_RUNOUT_SENSOR_DEBUG
40
 
40
 
41
-class FilamentSensorBase {
41
+class FilamentMonitorBase {
42
   public:
42
   public:
43
     static bool enabled;
43
     static bool enabled;
44
 
44
 
47
 };
47
 };
48
 
48
 
49
 template<class RESPONSE_T, class SENSOR_T>
49
 template<class RESPONSE_T, class SENSOR_T>
50
-class TFilamentSensor : public FilamentSensorBase {
50
+class TFilamentMonitor : public FilamentMonitorBase {
51
   private:
51
   private:
52
     typedef RESPONSE_T response_t;
52
     typedef RESPONSE_T response_t;
53
     typedef SENSOR_T   sensor_t;
53
     typedef SENSOR_T   sensor_t;
54
-    static response_t response;
55
-    static sensor_t   sensor;
54
+    static  response_t response;
55
+    static  sensor_t   sensor;
56
 
56
 
57
   public:
57
   public:
58
-    static void setup() {
58
+    static inline void setup() {
59
       sensor.setup();
59
       sensor.setup();
60
+      reset();
60
     }
61
     }
61
 
62
 
62
     static inline void reset() {
63
     static inline void reset() {
64
       response.reset();
65
       response.reset();
65
     }
66
     }
66
 
67
 
67
-    // The sensor calls this method when filament is present
68
+    // Call this method when filament is present,
69
+    // so the response can reset its counter.
68
     static inline void filament_present(const uint8_t extruder) {
70
     static inline void filament_present(const uint8_t extruder) {
69
       response.filament_present(extruder);
71
       response.filament_present(extruder);
70
     }
72
     }
71
 
73
 
72
-    static inline void block_complete(const block_t *b) {
73
-      response.block_complete(b);
74
-      sensor.block_complete(b);
74
+    // Handle a block completion. RunoutResponseDelayed uses this to
75
+    // add up the length of filament moved while the filament is out.
76
+    static inline void block_completed(const block_t* const b) {
77
+      if (enabled) {
78
+        response.block_completed(b);
79
+        sensor.block_completed(b);
80
+      }
75
     }
81
     }
76
 
82
 
77
-    static void run() {
83
+    // Give the response a chance to update its counter.
84
+    static inline void run() {
78
       if (enabled && !filament_ran_out && (IS_SD_PRINTING() || print_job_timer.isRunning())) {
85
       if (enabled && !filament_ran_out && (IS_SD_PRINTING() || print_job_timer.isRunning())) {
86
+        #if FILAMENT_RUNOUT_DISTANCE_MM > 0
87
+          cli(); // Prevent RunoutResponseDelayed::block_completed from accumulating here
88
+        #endif
79
         response.run();
89
         response.run();
80
         sensor.run();
90
         sensor.run();
81
-        if (response.has_runout()) {
91
+        const bool ran_out = response.has_run_out();
92
+        #if FILAMENT_RUNOUT_DISTANCE_MM > 0
93
+          sei();
94
+        #endif
95
+        if (ran_out) {
82
           filament_ran_out = true;
96
           filament_ran_out = true;
83
           #if ENABLED(EXTENSIBLE_UI)
97
           #if ENABLED(EXTENSIBLE_UI)
84
             UI::onFilamentRunout();
98
             UI::onFilamentRunout();
92
 
106
 
93
 /*************************** FILAMENT PRESENCE SENSORS ***************************/
107
 /*************************** FILAMENT PRESENCE SENSORS ***************************/
94
 
108
 
95
-class FilamentSensorTypeBase {
109
+class FilamentSensorBase {
96
   protected:
110
   protected:
97
     static void filament_present(const uint8_t extruder);
111
     static void filament_present(const uint8_t extruder);
98
 
112
 
153
     }
167
     }
154
 };
168
 };
155
 
169
 
156
-/**
157
- * This sensor is a simple endstop
158
- * switch in the path of the filament. It detects
159
- * filament runout, but not stripouts or jams.
160
- */
170
+#if ENABLED(FILAMENT_MOTION_SENSOR)
161
 
171
 
162
-class FilamentSensorTypeSwitch : public FilamentSensorTypeBase {
163
-  private:
164
-    static bool poll_runout_pin(const uint8_t extruder) {
165
-      const uint8_t runout_bits = poll_runout_pins();
166
-      #if NUM_RUNOUT_SENSORS == 1
167
-        return runout_bits;                     // A single sensor applying to all extruders
168
-      #else
169
-        #if ENABLED(DUAL_X_CARRIAGE)
170
-          if (dual_x_carriage_mode == DXC_DUPLICATION_MODE || dual_x_carriage_mode == DXC_SCALED_DUPLICATION_MODE)
171
-            return runout_bits;                 // Any extruder
172
-          else
173
-        #elif ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
174
-          if (extruder_duplication_enabled)
175
-            return runout_bits;                 // Any extruder
176
-          else
172
+  /**
173
+   * This sensor uses a magnetic encoder disc and a Hall effect
174
+   * sensor (or a slotted disc and optical sensor). The state
175
+   * will toggle between 0 and 1 on filament movement. It can detect
176
+   * filament runout and stripouts or jams.
177
+   */
178
+  class FilamentSensorEncoder : public FilamentSensorBase {
179
+    private:
180
+      static uint8_t motion_detected;
181
+
182
+      static inline void poll_motion_sensor() {
183
+        static uint8_t old_state;
184
+        const uint8_t new_state = poll_runout_pins(),
185
+                      change    = old_state ^ new_state;
186
+        old_state = new_state;
187
+
188
+        #ifdef FILAMENT_RUNOUT_SENSOR_DEBUG
189
+          if (change) SERIAL_PROTOCOLLNPAIR("Motion detected: ", int(change));
177
         #endif
190
         #endif
178
-            return TEST(runout_bits, extruder); // Specific extruder
179
-      #endif
180
-    }
181
 
191
 
182
-  public:
183
-    static inline void block_complete(const block_t *b) {}
192
+        motion_detected |= change;
193
+      }
184
 
194
 
185
-    static inline void run() {
186
-      if (!poll_runout_pin(active_extruder))
187
-        filament_present(active_extruder);
188
-    }
189
-};
195
+    public:
196
+      static inline void block_completed(const block_t* const b) {
197
+        // If the sensor wheel has moved since the last call to
198
+        // this method reset the runout counter for the extruder.
199
+        if (TEST(motion_detected, b->extruder))
200
+          filament_present(b->extruder);
201
+
202
+        // Clear motion triggers for next block
203
+        motion_detected = 0;
204
+      }
190
 
205
 
191
-// This filament sensor uses a magnetic encoder disc and a hall
192
-// effect sensor (or a slitted disc and an optical sensor). The state
193
-// will toggle between 0 and 1 with filament movement. It can detect
194
-// filament runout and stripouts or jams.
206
+      static inline void run() { poll_motion_sensor(); }
207
+  };
195
 
208
 
196
-class FilamentSensorTypeEncoder : public FilamentSensorTypeBase {
197
-  private:
198
-    static uint8_t motion_detected, old_state;
209
+#else
199
 
210
 
200
-    static void poll_motion_sensor() {
201
-      const uint8_t new_state = poll_runout_pins(),
202
-                    change    = old_state ^ new_state;
203
-      old_state = new_state;
211
+  /**
212
+   * This is a simple endstop switch in the path of the filament.
213
+   * It can detect filament runout, but not stripouts or jams.
214
+   */
215
+  class FilamentSensorSwitch : public FilamentSensorBase {
216
+    private:
217
+      static bool poll_runout_pin(const uint8_t extruder) {
218
+        const uint8_t runout_bits = poll_runout_pins();
219
+        #if NUM_RUNOUT_SENSORS == 1
220
+          return runout_bits;                     // A single sensor applying to all extruders
221
+        #else
222
+          #if ENABLED(DUAL_X_CARRIAGE)
223
+            if (dual_x_carriage_mode == DXC_DUPLICATION_MODE || dual_x_carriage_mode == DXC_SCALED_DUPLICATION_MODE)
224
+              return runout_bits;                 // Any extruder
225
+            else
226
+          #elif ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
227
+            if (extruder_duplication_enabled)
228
+              return runout_bits;                 // Any extruder
229
+            else
230
+          #endif
231
+              return TEST(runout_bits, extruder); // Specific extruder
232
+        #endif
233
+      }
204
 
234
 
205
-      #ifdef FILAMENT_RUNOUT_SENSOR_DEBUG
206
-        if (change) SERIAL_PROTOCOLLNPAIR("motion detected: ", change);
207
-      #endif
235
+    public:
236
+      static inline void block_completed(const block_t* const b) {}
208
 
237
 
209
-      motion_detected |= change;
210
-    }
238
+      static inline void run() {
239
+        const bool out = poll_runout_pin(active_extruder);
240
+        if (!out) filament_present(active_extruder);
241
+        #ifdef FILAMENT_RUNOUT_SENSOR_DEBUG
242
+          static bool was_out = false;
243
+          if (out != was_out) {
244
+            was_out = out;
245
+            SERIAL_PROTOCOL("Filament ");
246
+            serialprintPGM(out ? PSTR("OUT\n") : PSTR("IN\n"));
247
+          }
248
+        #endif
249
+      }
250
+  };
211
 
251
 
212
-  public:
213
-    static void block_complete(const block_t *b) {
214
-      // If the just-executed block caused the sensor wheel
215
-      // to turn, reset the runout counter for that extruder.
216
-      if (TEST(motion_detected, b->extruder))
217
-        filament_present(b->extruder);
218
-
219
-      // Clear motion triggers for next block
220
-      motion_detected = 0;
221
-    }
222
 
252
 
223
-    static inline void run() { poll_motion_sensor(); }
224
-};
253
+#endif // !FILAMENT_MOTION_SENSOR
225
 
254
 
226
 /********************************* RESPONSE TYPE *********************************/
255
 /********************************* RESPONSE TYPE *********************************/
227
 
256
 
228
 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
257
 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
229
 
258
 
230
-  // The RunoutResponseDelayed will trigger an runout event only after
231
-  // RUNOUT_DISTANCE_MM of filament have been fed after a runout condition.
259
+  // RunoutResponseDelayed triggers a runout event only if the length
260
+  // of filament specified by FILAMENT_RUNOUT_DISTANCE_MM has been fed
261
+  // during a runout condition.
232
   class RunoutResponseDelayed {
262
   class RunoutResponseDelayed {
233
     private:
263
     private:
234
-      static int32_t steps_since_detection[EXTRUDERS];
235
-
236
-      static float get_mm_since_runout(const uint8_t extruder) {
237
-        return (steps_since_detection[extruder] / planner.settings.axis_steps_per_mm[E_AXIS_N(extruder)]);
238
-      }
264
+      static volatile float runout_mm_countdown[EXTRUDERS];
239
 
265
 
240
     public:
266
     public:
241
       static float runout_distance_mm;
267
       static float runout_distance_mm;
242
 
268
 
243
-      static inline bool has_runout() {
244
-        return get_mm_since_runout(active_extruder) > runout_distance_mm;
245
-      }
246
-
247
-      static inline void filament_present(const uint8_t extruder) {
248
-        steps_since_detection[extruder] = 0;
269
+      static void reset() {
270
+        LOOP_L_N(i, EXTRUDERS) filament_present(i);
249
       }
271
       }
250
 
272
 
251
       static inline void run() {
273
       static inline void run() {
252
         #ifdef FILAMENT_RUNOUT_SENSOR_DEBUG
274
         #ifdef FILAMENT_RUNOUT_SENSOR_DEBUG
253
-          static uint16_t r = 0;
254
-          if ((r++ % 24000) == 0) {
255
-            SERIAL_PROTOCOLPGM("mm since filament detection: ");
256
-            LOOP_L_N(i, NUM_RUNOUT_SENSORS) {
257
-              if (i > 0) SERIAL_PROTOCOLPGM(", ");
258
-              SERIAL_PROTOCOL(get_mm_since_runout(i));
275
+          static millis_t t = 0;
276
+          const millis_t ms = millis();
277
+          if (ELAPSED(ms, t)) {
278
+            t = millis() + 1000UL;
279
+            LOOP_L_N(i, EXTRUDERS) {
280
+              serialprintPGM(i ? PSTR(", ") : PSTR("Remaining mm: "));
281
+              SERIAL_PROTOCOL(runout_mm_countdown[i]);
259
             }
282
             }
260
             SERIAL_EOL();
283
             SERIAL_EOL();
261
           }
284
           }
262
         #endif
285
         #endif
263
       }
286
       }
264
 
287
 
265
-      static void reset() {
266
-        LOOP_L_N(i, NUM_RUNOUT_SENSORS) steps_since_detection[i] = 0;
288
+      static inline bool has_run_out() {
289
+        return runout_mm_countdown[active_extruder] < 0;
290
+      }
291
+
292
+      static inline void filament_present(const uint8_t extruder) {
293
+        runout_mm_countdown[extruder] = runout_distance_mm;
267
       }
294
       }
268
 
295
 
269
-      static inline void block_complete(const block_t *b) {
270
-        steps_since_detection[b->extruder] += TEST(b->direction_bits, E_AXIS) ? -b->steps[E_AXIS] : b->steps[E_AXIS];
296
+      static inline void block_completed(const block_t* const b) {
297
+        const uint8_t e = b->extruder;
298
+        const int32_t steps = b->steps[E_AXIS];
299
+        runout_mm_countdown[e] -= (TEST(b->direction_bits, E_AXIS) ? -steps : steps) * planner.steps_to_mm[E_AXIS_N(e)];
271
       }
300
       }
272
   };
301
   };
273
 
302
 
274
 #else // !FILAMENT_RUNOUT_DISTANCE_MM
303
 #else // !FILAMENT_RUNOUT_DISTANCE_MM
275
 
304
 
276
-  // The RunoutResponseDebounced will trigger an runout event after
277
-  // a runout condition is detected FIL_RUNOUT_THRESHOLD times in a row.
305
+  // RunoutResponseDebounced triggers a runout event after a runout
306
+  // condition has been detected runout_threshold times in a row.
278
 
307
 
279
   class RunoutResponseDebounced {
308
   class RunoutResponseDebounced {
280
     private:
309
     private:
281
-      static constexpr uint8_t FIL_RUNOUT_THRESHOLD = 5;
282
-      static uint8_t runout_count;
310
+      static constexpr int8_t runout_threshold = 5;
311
+      static int8_t runout_count;
283
     public:
312
     public:
284
-      static inline bool has_runout()                             { return runout_count > FIL_RUNOUT_THRESHOLD; }
285
-      static inline void block_complete(const block_t *b)         {}
286
-      static inline void filament_present(const uint8_t extruder) { runout_count = 0; UNUSED(extruder); }
287
-      static inline void run()                                    { runout_count++; }
288
-      static inline void reset()                                  { runout_count = 0; }
313
+      static inline void reset()                                  { runout_count = runout_threshold; }
314
+      static inline void run()                                    { runout_count--; }
315
+      static inline bool has_run_out()                            { return runout_count < 0; }
316
+      static inline void block_completed(const block_t* const b)  {}
317
+      static inline void filament_present(const uint8_t extruder) { runout_count = runout_threshold; UNUSED(extruder); }
289
   };
318
   };
290
 
319
 
291
 #endif // !FILAMENT_RUNOUT_DISTANCE_MM
320
 #endif // !FILAMENT_RUNOUT_DISTANCE_MM
292
 
321
 
293
 /********************************* TEMPLATE SPECIALIZATION *********************************/
322
 /********************************* TEMPLATE SPECIALIZATION *********************************/
294
 
323
 
295
-typedef TFilamentSensor<
324
+typedef TFilamentMonitor<
296
   #if FILAMENT_RUNOUT_DISTANCE_MM > 0
325
   #if FILAMENT_RUNOUT_DISTANCE_MM > 0
297
     #if ENABLED(FILAMENT_MOTION_SENSOR)
326
     #if ENABLED(FILAMENT_MOTION_SENSOR)
298
-      RunoutResponseDelayed, FilamentSensorTypeEncoder
327
+      RunoutResponseDelayed, FilamentSensorEncoder
299
     #else
328
     #else
300
-      RunoutResponseDelayed, FilamentSensorTypeSwitch
329
+      RunoutResponseDelayed, FilamentSensorSwitch
301
     #endif
330
     #endif
302
   #else
331
   #else
303
-    RunoutResponseDebounced, FilamentSensorTypeSwitch
332
+    RunoutResponseDebounced, FilamentSensorSwitch
304
   #endif
333
   #endif
305
-> FilamentRunoutSensor;
334
+> FilamentMonitor;
306
 
335
 
307
-extern FilamentRunoutSensor runout;
336
+extern FilamentMonitor runout;

+ 1
- 1
Marlin/src/module/stepper.cpp View File

1492
     // If current block is finished, reset pointer
1492
     // If current block is finished, reset pointer
1493
     if (step_events_completed >= step_event_count) {
1493
     if (step_events_completed >= step_event_count) {
1494
       #if FILAMENT_RUNOUT_DISTANCE_MM > 0
1494
       #if FILAMENT_RUNOUT_DISTANCE_MM > 0
1495
-        runout.block_complete(current_block);
1495
+        runout.block_completed(current_block);
1496
       #endif
1496
       #endif
1497
       axis_did_move = 0;
1497
       axis_did_move = 0;
1498
       current_block = NULL;
1498
       current_block = NULL;

+ 1
- 1
Marlin/src/pins/pins.h View File

149
 #elif MB(RAMPS_ENDER_4)
149
 #elif MB(RAMPS_ENDER_4)
150
   #include "pins_RAMPS_ENDER_4.h"     // ATmega2560                                 env:megaatmega2560
150
   #include "pins_RAMPS_ENDER_4.h"     // ATmega2560                                 env:megaatmega2560
151
 #elif MB(RAMPS_CREALITY)
151
 #elif MB(RAMPS_CREALITY)
152
-  #include "pins_RAMPS_CREALITY.h"     // ATmega2560                                 env:megaatmega2560
152
+  #include "pins_RAMPS_CREALITY.h"    // ATmega2560                                 env:megaatmega2560
153
 #elif MB(FYSETC_F6_13)
153
 #elif MB(FYSETC_F6_13)
154
   #include "pins_FYSETC_F6_13.h"      // ATmega2560                                 env:megaatmega2560
154
   #include "pins_FYSETC_F6_13.h"      // ATmega2560                                 env:megaatmega2560
155
 
155
 

Loading…
Cancel
Save