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,23 +30,29 @@
30 30
 
31 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 51
 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
46 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 54
 #else
49
-  uint8_t RunoutResponseDebounced::runout_count; // = 0
55
+  int8_t RunoutResponseDebounced::runout_count; // = 0
50 56
 #endif
51 57
 
52 58
 #endif // FILAMENT_RUNOUT_SENSOR

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

@@ -38,7 +38,7 @@
38 38
 
39 39
 //#define FILAMENT_RUNOUT_SENSOR_DEBUG
40 40
 
41
-class FilamentSensorBase {
41
+class FilamentMonitorBase {
42 42
   public:
43 43
     static bool enabled;
44 44
 
@@ -47,16 +47,17 @@ class FilamentSensorBase {
47 47
 };
48 48
 
49 49
 template<class RESPONSE_T, class SENSOR_T>
50
-class TFilamentSensor : public FilamentSensorBase {
50
+class TFilamentMonitor : public FilamentMonitorBase {
51 51
   private:
52 52
     typedef RESPONSE_T response_t;
53 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 57
   public:
58
-    static void setup() {
58
+    static inline void setup() {
59 59
       sensor.setup();
60
+      reset();
60 61
     }
61 62
 
62 63
     static inline void reset() {
@@ -64,21 +65,34 @@ class TFilamentSensor : public FilamentSensorBase {
64 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 70
     static inline void filament_present(const uint8_t extruder) {
69 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 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 89
         response.run();
80 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 96
           filament_ran_out = true;
83 97
           #if ENABLED(EXTENSIBLE_UI)
84 98
             UI::onFilamentRunout();
@@ -92,7 +106,7 @@ class TFilamentSensor : public FilamentSensorBase {
92 106
 
93 107
 /*************************** FILAMENT PRESENCE SENSORS ***************************/
94 108
 
95
-class FilamentSensorTypeBase {
109
+class FilamentSensorBase {
96 110
   protected:
97 111
     static void filament_present(const uint8_t extruder);
98 112
 
@@ -153,155 +167,170 @@ class FilamentSensorTypeBase {
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 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 255
 /********************************* RESPONSE TYPE *********************************/
227 256
 
228 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 262
   class RunoutResponseDelayed {
233 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 266
     public:
241 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 273
       static inline void run() {
252 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 283
             SERIAL_EOL();
261 284
           }
262 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 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 308
   class RunoutResponseDebounced {
280 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 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 320
 #endif // !FILAMENT_RUNOUT_DISTANCE_MM
292 321
 
293 322
 /********************************* TEMPLATE SPECIALIZATION *********************************/
294 323
 
295
-typedef TFilamentSensor<
324
+typedef TFilamentMonitor<
296 325
   #if FILAMENT_RUNOUT_DISTANCE_MM > 0
297 326
     #if ENABLED(FILAMENT_MOTION_SENSOR)
298
-      RunoutResponseDelayed, FilamentSensorTypeEncoder
327
+      RunoutResponseDelayed, FilamentSensorEncoder
299 328
     #else
300
-      RunoutResponseDelayed, FilamentSensorTypeSwitch
329
+      RunoutResponseDelayed, FilamentSensorSwitch
301 330
     #endif
302 331
   #else
303
-    RunoutResponseDebounced, FilamentSensorTypeSwitch
332
+    RunoutResponseDebounced, FilamentSensorSwitch
304 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,7 +1492,7 @@ uint32_t Stepper::stepper_block_phase_isr() {
1492 1492
     // If current block is finished, reset pointer
1493 1493
     if (step_events_completed >= step_event_count) {
1494 1494
       #if FILAMENT_RUNOUT_DISTANCE_MM > 0
1495
-        runout.block_complete(current_block);
1495
+        runout.block_completed(current_block);
1496 1496
       #endif
1497 1497
       axis_did_move = 0;
1498 1498
       current_block = NULL;

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

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

Loading…
Cancel
Save