Browse Source

MMU2 Extruder Sensor support (#17886)

Bastien R 5 years ago
parent
commit
2ec482a102
No account linked to committer's email address

+ 20
- 2
Marlin/Configuration_adv.h View File

3279
     // This is for Prusa MK3-style extruders. Customize for your hardware.
3279
     // This is for Prusa MK3-style extruders. Customize for your hardware.
3280
     #define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0
3280
     #define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0
3281
     #define MMU2_LOAD_TO_NOZZLE_SEQUENCE \
3281
     #define MMU2_LOAD_TO_NOZZLE_SEQUENCE \
3282
-      {  7.2,  562 }, \
3282
+      {  7.2, 1145 }, \
3283
       { 14.4,  871 }, \
3283
       { 14.4,  871 }, \
3284
       { 36.0, 1393 }, \
3284
       { 36.0, 1393 }, \
3285
       { 14.4,  871 }, \
3285
       { 14.4,  871 }, \
3299
       { -50.0, 2000 }
3299
       { -50.0, 2000 }
3300
   #endif
3300
   #endif
3301
 
3301
 
3302
-  // Using a sensor like the MMU2S
3302
+  /**
3303
+   * MMU Extruder Sensor
3304
+   * Add support for Prusa IR Sensor (or other) to detect that filament reach the extruder to make loading filament more reliable
3305
+   * If your extruder is equipped with a filament sensor located less than 38mm from the gears you can use this feature
3306
+   * During loading to the extruder, the sensor will stop the loading command when he's triggered and make a last move to load filament to the gears
3307
+   * If no filament is detected, MMU2 will make more loading attemps, if finally no filament is detected, the printer will enter in runout state
3308
+   */
3309
+
3310
+  //#define MMU_EXTRUDER_SENSOR
3311
+  #if ENABLED(MMU_EXTRUDER_SENSOR) 
3312
+    #define MMU_LOADING_ATTEMPTS_NR 5 //max. number of attempts to load filament if first load fail
3313
+  #endif
3314
+
3315
+  /**
3316
+   * Using a sensor like the MMU2S
3317
+   * This mode only work if you have a MK3S extruder with sensor sensing the extruder idler mmu2s
3318
+   * See https://help.prusa3d.com/en/guide/3b-mk3s-mk2-5s-extruder-upgrade_41560, step 11
3319
+   */
3320
+
3303
   //#define PRUSA_MMU2_S_MODE
3321
   //#define PRUSA_MMU2_S_MODE
3304
   #if ENABLED(PRUSA_MMU2_S_MODE)
3322
   #if ENABLED(PRUSA_MMU2_S_MODE)
3305
     #define MMU2_C0_RETRY   5             // Number of retries (total time = timeout*retries)
3323
     #define MMU2_C0_RETRY   5             // Number of retries (total time = timeout*retries)

+ 245
- 55
Marlin/src/feature/mmu2/mmu2.cpp View File

51
 
51
 
52
 #define MMU_TODELAY 100
52
 #define MMU_TODELAY 100
53
 #define MMU_TIMEOUT 10
53
 #define MMU_TIMEOUT 10
54
-#define MMU_CMD_TIMEOUT 60000ul // 5min timeout for mmu commands (except P0)
55
-#define MMU_P0_TIMEOUT 3000ul   // Timeout for P0 command: 3seconds
54
+#define MMU_CMD_TIMEOUT 45000UL // 45s timeout for mmu commands (except P0)
55
+#define MMU_P0_TIMEOUT 3000UL   // Timeout for P0 command: 3seconds
56
+
57
+#if ENABLED(MMU_EXTRUDER_SENSOR)
58
+  uint8_t mmu_idl_sens = 0;
59
+  static bool mmu_loading_flag = false;
60
+#endif
56
 
61
 
57
 #define MMU_CMD_NONE 0
62
 #define MMU_CMD_NONE 0
58
 #define MMU_CMD_T0   0x10
63
 #define MMU_CMD_T0   0x10
79
 #define MMU_CMD_F3   0x73
84
 #define MMU_CMD_F3   0x73
80
 #define MMU_CMD_F4   0x74
85
 #define MMU_CMD_F4   0x74
81
 
86
 
82
-#if ENABLED(MMU2_MODE_12V)
83
-  #define MMU_REQUIRED_FW_BUILDNR 132
84
-#else
85
-  #define MMU_REQUIRED_FW_BUILDNR 126
86
-#endif
87
+#define MMU_REQUIRED_FW_BUILDNR TERN(MMU2_MODE_12V, 132, 126)
87
 
88
 
88
 #define MMU2_NO_TOOL 99
89
 #define MMU2_NO_TOOL 99
89
 #define MMU_BAUD    115200
90
 #define MMU_BAUD    115200
99
 volatile int8_t MMU2::finda = 1;
100
 volatile int8_t MMU2::finda = 1;
100
 volatile bool MMU2::finda_runout_valid;
101
 volatile bool MMU2::finda_runout_valid;
101
 int16_t MMU2::version = -1, MMU2::buildnr = -1;
102
 int16_t MMU2::version = -1, MMU2::buildnr = -1;
102
-millis_t MMU2::last_request, MMU2::next_P0_request;
103
+millis_t MMU2::prev_request, MMU2::prev_P0_request;
103
 char MMU2::rx_buffer[MMU_RX_SIZE], MMU2::tx_buffer[MMU_TX_SIZE];
104
 char MMU2::rx_buffer[MMU_RX_SIZE], MMU2::tx_buffer[MMU_TX_SIZE];
104
 
105
 
105
 #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
106
 #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
159
   return extruder == MMU2_NO_TOOL ? -1 : extruder;
160
   return extruder == MMU2_NO_TOOL ? -1 : extruder;
160
 }
161
 }
161
 
162
 
163
+#if EITHER(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR)
164
+  #define FILAMENT_PRESENT() (READ(FIL_RUNOUT_PIN) != FIL_RUNOUT_INVERTING)
165
+#endif
166
+
162
 void MMU2::mmu_loop() {
167
 void MMU2::mmu_loop() {
163
 
168
 
164
   switch (state) {
169
   switch (state) {
248
           int filament = cmd - MMU_CMD_T0;
253
           int filament = cmd - MMU_CMD_T0;
249
           DEBUG_ECHOLNPAIR("MMU <= T", filament);
254
           DEBUG_ECHOLNPAIR("MMU <= T", filament);
250
           tx_printf_P(PSTR("T%d\n"), filament);
255
           tx_printf_P(PSTR("T%d\n"), filament);
256
+          TERN_(MMU_EXTRUDER_SENSOR, mmu_idl_sens = 1); // enable idler sensor, if any
251
           state = 3; // wait for response
257
           state = 3; // wait for response
252
         }
258
         }
253
         else if (WITHIN(cmd, MMU_CMD_L0, MMU_CMD_L4)) {
259
         else if (WITHIN(cmd, MMU_CMD_L0, MMU_CMD_L4)) {
296
         last_cmd = cmd;
302
         last_cmd = cmd;
297
         cmd = MMU_CMD_NONE;
303
         cmd = MMU_CMD_NONE;
298
       }
304
       }
299
-      else if (ELAPSED(millis(), next_P0_request)) {
305
+      else if (ELAPSED(millis(), prev_P0_request + 300)) {
300
         // read FINDA
306
         // read FINDA
301
         tx_str_P(PSTR("P0\n"));
307
         tx_str_P(PSTR("P0\n"));
302
         state = 2; // wait for response
308
         state = 2; // wait for response
312
         // This is super annoying. Only activate if necessary
318
         // This is super annoying. Only activate if necessary
313
         // if (finda_runout_valid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6);
319
         // if (finda_runout_valid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6);
314
 
320
 
315
-        state = 1;
316
-
317
-        if (cmd == 0) ready = true;
318
-
319
         if (!finda && finda_runout_valid) filament_runout();
321
         if (!finda && finda_runout_valid) filament_runout();
322
+        if (cmd == 0) ready = true;
323
+        state = 1;
320
       }
324
       }
321
-      else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s)
325
+      else if (ELAPSED(millis(), prev_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s)
322
         state = 1;
326
         state = 1;
323
 
327
 
324
       TERN_(PRUSA_MMU2_S_MODE, check_filament());
328
       TERN_(PRUSA_MMU2_S_MODE, check_filament());
325
       break;
329
       break;
326
 
330
 
327
     case 3:   // response to mmu commands
331
     case 3:   // response to mmu commands
332
+      #if ENABLED(MMU_EXTRUDER_SENSOR)
333
+        if (mmu_idl_sens) {
334
+          if (FILAMENT_PRESENT() && mmu_loading_flag) {
335
+            DEBUG_ECHOLNPGM("MMU <= 'A'\n");
336
+            tx_str_P(PSTR("A\n")); // send 'abort' request
337
+            mmu_idl_sens = 0;
338
+            DEBUG_ECHOLNPGM("MMU IDLER_SENSOR = 0 - ABORT\n");
339
+          }
340
+        }
341
+      #endif
342
+
328
       if (rx_ok()) {
343
       if (rx_ok()) {
329
         DEBUG_ECHOLNPGM("MMU => 'ok'");
344
         DEBUG_ECHOLNPGM("MMU => 'ok'");
330
         ready = true;
345
         ready = true;
331
         state = 1;
346
         state = 1;
332
         last_cmd = MMU_CMD_NONE;
347
         last_cmd = MMU_CMD_NONE;
333
       }
348
       }
334
-      else if (ELAPSED(millis(), last_request + MMU_CMD_TIMEOUT)) {
349
+      else if (ELAPSED(millis(), prev_request + MMU_CMD_TIMEOUT)) {
335
         // resend request after timeout
350
         // resend request after timeout
336
         if (last_cmd) {
351
         if (last_cmd) {
337
           DEBUG_ECHOLNPGM("MMU retry");
352
           DEBUG_ECHOLNPGM("MMU retry");
351
 bool MMU2::rx_start() {
366
 bool MMU2::rx_start() {
352
   // check for start message
367
   // check for start message
353
   if (rx_str_P(PSTR("start\n"))) {
368
   if (rx_str_P(PSTR("start\n"))) {
354
-    next_P0_request = millis() + 300;
369
+    prev_P0_request = millis();
355
     return true;
370
     return true;
356
   }
371
   }
357
   return false;
372
   return false;
397
   uint8_t len = strlen_P(str);
412
   uint8_t len = strlen_P(str);
398
   LOOP_L_N(i, len) mmuSerial.write(pgm_read_byte(str++));
413
   LOOP_L_N(i, len) mmuSerial.write(pgm_read_byte(str++));
399
   rx_buffer[0] = '\0';
414
   rx_buffer[0] = '\0';
400
-  last_request = millis();
415
+  prev_request = millis();
401
 }
416
 }
402
 
417
 
403
 /**
418
 /**
408
   uint8_t len = sprintf_P(tx_buffer, format, argument);
423
   uint8_t len = sprintf_P(tx_buffer, format, argument);
409
   LOOP_L_N(i, len) mmuSerial.write(tx_buffer[i]);
424
   LOOP_L_N(i, len) mmuSerial.write(tx_buffer[i]);
410
   rx_buffer[0] = '\0';
425
   rx_buffer[0] = '\0';
411
-  last_request = millis();
426
+  prev_request = millis();
412
 }
427
 }
413
 
428
 
414
 /**
429
 /**
419
   uint8_t len = sprintf_P(tx_buffer, format, argument1, argument2);
434
   uint8_t len = sprintf_P(tx_buffer, format, argument1, argument2);
420
   LOOP_L_N(i, len) mmuSerial.write(tx_buffer[i]);
435
   LOOP_L_N(i, len) mmuSerial.write(tx_buffer[i]);
421
   rx_buffer[0] = '\0';
436
   rx_buffer[0] = '\0';
422
-  last_request = millis();
437
+  prev_request = millis();
423
 }
438
 }
424
 
439
 
425
 /**
440
 /**
435
  */
450
  */
436
 bool MMU2::rx_ok() {
451
 bool MMU2::rx_ok() {
437
   if (rx_str_P(PSTR("ok\n"))) {
452
   if (rx_str_P(PSTR("ok\n"))) {
438
-    next_P0_request = millis() + 300;
453
+    prev_P0_request = millis();
439
     return true;
454
     return true;
440
   }
455
   }
441
   return false;
456
   return false;
476
     return success;
491
     return success;
477
   }
492
   }
478
 
493
 
479
-#endif
494
+  /**
495
+   * Handle tool change
496
+   */
497
+  void MMU2::tool_change(const uint8_t index) {
498
+
499
+    if (!enabled) return;
500
+
501
+    set_runout_valid(false);
502
+
503
+    if (index != extruder) {
504
+
505
+      DISABLE_AXIS_E0();
506
+      ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
507
+
508
+      command(MMU_CMD_T0 + index);
509
+      manage_response(true, true);
510
+
511
+      if (load_to_gears()) {
512
+        extruder = index; // filament change is finished
513
+        active_extruder = 0;
514
+        ENABLE_AXIS_E0();
515
+        SERIAL_ECHO_START();
516
+        SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder));
517
+      }
518
+      ui.reset_status();
519
+    }
520
+
521
+    set_runout_valid(true);
522
+  }
523
+
524
+  /**
525
+   * Handle special T?/Tx/Tc commands
526
+   *
527
+   * T? Gcode to extrude shouldn't have to follow, load to extruder wheels is done automatically
528
+   * Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load.
529
+   * Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated.
530
+   */
531
+  void MMU2::tool_change(const char* special) {
532
+
533
+    if (!enabled) return;
534
+
535
+    #if ENABLED(MMU2_MENUS)
536
+
537
+      set_runout_valid(false);
538
+
539
+      switch (*special) {
540
+        case '?': {
541
+          uint8_t index = mmu2_choose_filament();
542
+          while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
543
+          load_filament_to_nozzle(index);
544
+        } break;
545
+
546
+        case 'x': {
547
+          planner.synchronize();
548
+          uint8_t index = mmu2_choose_filament();
549
+          DISABLE_AXIS_E0();
550
+          command(MMU_CMD_T0 + index);
551
+          manage_response(true, true);
552
+
553
+          if (load_to_gears()) {
554
+            mmu_loop();
555
+            ENABLE_AXIS_E0();
556
+            extruder = index;
557
+            active_extruder = 0;
558
+          }
559
+        } break;
560
+
561
+        case 'c': {
562
+          while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
563
+          execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
564
+        } break;
565
+      }
566
+
567
+      set_runout_valid(true);
568
+
569
+    #endif // MMU2_MENUS
570
+  }
571
+
572
+#elif ENABLED(MMU_EXTRUDER_SENSOR)
573
+
574
+  /**
575
+   * Handle tool change
576
+   */
577
+  void MMU2::tool_change(const uint8_t index) {
578
+    if (!enabled) return;
579
+
580
+    set_runout_valid(false);
581
+
582
+    if (index != extruder) {
583
+      DISABLE_AXIS_E0();
584
+      if (FILAMENT_PRESENT()) {
585
+        DEBUG_ECHOLNPGM("Unloading\n");
586
+        mmu_loading_flag = false;
587
+        command(MMU_CMD_U0);
588
+        manage_response(true, true);
589
+      }
590
+      ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
591
+      mmu_loading_flag = true;
592
+      command(MMU_CMD_T0 + index);
593
+      manage_response(true, true);
594
+      mmu_continue_loading();
595
+      command(MMU_CMD_C0);
596
+      extruder = index;
597
+      active_extruder = 0;
598
+
599
+      ENABLE_AXIS_E0();
600
+      SERIAL_ECHO_START();
601
+      SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder));
602
+
603
+      ui.reset_status();
604
+    }
605
+
606
+    set_runout_valid(true);
607
+  }
608
+
609
+  /**
610
+   * Handle special T?/Tx/Tc commands
611
+   *
612
+   * T? Gcode to extrude shouldn't have to follow, load to extruder wheels is done automatically
613
+   * Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load.
614
+   * Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated.
615
+   */
616
+  void MMU2::tool_change(const char* special) {
617
+    if (!enabled) return;
618
+
619
+    #if ENABLED(MMU2_MENUS)
620
+
621
+      set_runout_valid(false);
622
+
623
+      switch (*special) {
624
+        case '?': {
625
+          DEBUG_ECHOLNPGM("case ?\n");
626
+          uint8_t index = mmu2_choose_filament();
627
+          while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
628
+          load_filament_to_nozzle(index);
629
+        } break;
630
+
631
+        case 'x': {
632
+          DEBUG_ECHOLNPGM("case x\n");
633
+          planner.synchronize();
634
+          uint8_t index = mmu2_choose_filament();
635
+          DISABLE_AXIS_E0();
636
+          command(MMU_CMD_T0 + index);
637
+          manage_response(true, true);
638
+          mmu_continue_loading();
639
+          command(MMU_CMD_C0);
640
+          mmu_loop();
641
+
642
+          ENABLE_AXIS_E0();
643
+          extruder = index;
644
+          active_extruder = 0;
645
+        } break;
646
+
647
+        case 'c': {
648
+          DEBUG_ECHOLNPGM("case c\n");
649
+          while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
650
+          execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
651
+        } break;
652
+      }
653
+
654
+      set_runout_valid(true);
655
+
656
+    #endif // MMU2_MENUS
657
+  }
658
+
659
+  void MMU2::mmu_continue_loading() {
660
+    for (uint8_t i = 0; i < MMU_LOADING_ATTEMPTS_NR; i++) {
661
+      DEBUG_ECHOLNPAIR("Additional load attempt #", i);
662
+      if (FILAMENT_PRESENT()) break;
663
+      command(MMU_CMD_C0);
664
+      manage_response(true, true);
665
+    }
666
+    if (!FILAMENT_PRESENT()) {
667
+      DEBUG_ECHOLNPGM("Filament never reached sensor, runout");
668
+      filament_runout();
669
+    }
670
+    mmu_idl_sens = 0;
671
+  }
672
+
673
+#elif DISABLED(MMU_EXTRUDER_SENSOR) && DISABLED(PRUSA_MMU2_S_MODE)
480
 
674
 
481
 /**
675
 /**
482
  * Handle tool change
676
  * Handle tool change
483
  */
677
  */
484
-void MMU2::tool_change(uint8_t index) {
485
-
678
+void MMU2::tool_change(const uint8_t index) {
486
   if (!enabled) return;
679
   if (!enabled) return;
487
 
680
 
488
   set_runout_valid(false);
681
   set_runout_valid(false);
489
 
682
 
490
   if (index != extruder) {
683
   if (index != extruder) {
491
-
492
     DISABLE_AXIS_E0();
684
     DISABLE_AXIS_E0();
493
     ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
685
     ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1));
494
-
495
     command(MMU_CMD_T0 + index);
686
     command(MMU_CMD_T0 + index);
496
     manage_response(true, true);
687
     manage_response(true, true);
497
-
498
-    if (load_to_gears()) {
499
-      extruder = index; // filament change is finished
500
-      active_extruder = 0;
501
-      ENABLE_AXIS_E0();
502
-      SERIAL_ECHO_START();
503
-      SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder));
504
-    }
688
+    command(MMU_CMD_C0);
689
+    extruder = index; //filament change is finished
690
+    active_extruder = 0;
691
+    ENABLE_AXIS_E0();
692
+    SERIAL_ECHO_START();
693
+    SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder));
505
     ui.reset_status();
694
     ui.reset_status();
506
   }
695
   }
507
 
696
 
518
  *
707
  *
519
  */
708
  */
520
 void MMU2::tool_change(const char* special) {
709
 void MMU2::tool_change(const char* special) {
521
-
522
   if (!enabled) return;
710
   if (!enabled) return;
523
 
711
 
524
   #if ENABLED(MMU2_MENUS)
712
   #if ENABLED(MMU2_MENUS)
527
 
715
 
528
     switch (*special) {
716
     switch (*special) {
529
       case '?': {
717
       case '?': {
718
+        DEBUG_ECHOLNPGM("case ?\n");
530
         uint8_t index = mmu2_choose_filament();
719
         uint8_t index = mmu2_choose_filament();
531
         while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
720
         while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
532
         load_filament_to_nozzle(index);
721
         load_filament_to_nozzle(index);
533
       } break;
722
       } break;
534
 
723
 
535
       case 'x': {
724
       case 'x': {
725
+        DEBUG_ECHOLNPGM("case x\n");
536
         planner.synchronize();
726
         planner.synchronize();
537
         uint8_t index = mmu2_choose_filament();
727
         uint8_t index = mmu2_choose_filament();
538
         DISABLE_AXIS_E0();
728
         DISABLE_AXIS_E0();
539
         command(MMU_CMD_T0 + index);
729
         command(MMU_CMD_T0 + index);
540
         manage_response(true, true);
730
         manage_response(true, true);
731
+        command(MMU_CMD_C0);
732
+        mmu_loop();
541
 
733
 
542
-        if (load_to_gears()) {
543
-          mmu_loop();
544
-          ENABLE_AXIS_E0();
545
-          extruder = index;
546
-          active_extruder = 0;
547
-        }
734
+        ENABLE_AXIS_E0();
735
+        extruder = index;
736
+        active_extruder = 0;
548
       } break;
737
       } break;
549
 
738
 
550
       case 'c': {
739
       case 'c': {
740
+        DEBUG_ECHOLNPGM("case c\n");
551
         while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
741
         while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);
552
         execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
742
         execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
553
       } break;
743
       } break;
556
     set_runout_valid(true);
746
     set_runout_valid(true);
557
 
747
 
558
   #endif
748
   #endif
559
-}
749
+  }
750
+
751
+#endif // MMU_EXTRUDER_SENSOR
560
 
752
 
561
 /**
753
 /**
562
  * Set next command
754
  * Set next command
593
   bool response = false;
785
   bool response = false;
594
   mmu_print_saved = false;
786
   mmu_print_saved = false;
595
   xyz_pos_t resume_position;
787
   xyz_pos_t resume_position;
596
-  int16_t resume_hotend_temp;
788
+  int16_t resume_hotend_temp = thermalManager.degTargetHotend(active_extruder);
597
 
789
 
598
   KEEPALIVE_STATE(PAUSED_FOR_USER);
790
   KEEPALIVE_STATE(PAUSED_FOR_USER);
599
 
791
 
652
   }
844
   }
653
 }
845
 }
654
 
846
 
655
-void MMU2::set_filament_type(uint8_t index, uint8_t filamentType) {
847
+void MMU2::set_filament_type(const uint8_t index, const uint8_t filamentType) {
656
   if (!enabled) return;
848
   if (!enabled) return;
657
 
849
 
658
   cmd_arg = filamentType;
850
   cmd_arg = filamentType;
667
 }
859
 }
668
 
860
 
669
 #if ENABLED(PRUSA_MMU2_S_MODE)
861
 #if ENABLED(PRUSA_MMU2_S_MODE)
862
+
670
   void MMU2::check_filament() {
863
   void MMU2::check_filament() {
671
-    const bool runout = READ(FIL_RUNOUT_PIN) ^ (FIL_RUNOUT_INVERTING);
672
-    if (runout && !mmu2s_triggered) {
864
+    const bool present = FILAMENT_PRESENT();
865
+    if (present && !mmu2s_triggered) {
673
       DEBUG_ECHOLNPGM("MMU <= 'A'");
866
       DEBUG_ECHOLNPGM("MMU <= 'A'");
674
       tx_str_P(PSTR("A\n"));
867
       tx_str_P(PSTR("A\n"));
675
     }
868
     }
676
-    mmu2s_triggered = runout;
869
+    mmu2s_triggered = present;
677
   }
870
   }
678
 
871
 
679
   bool MMU2::can_load() {
872
   bool MMU2::can_load() {
680
     execute_extruder_sequence((const E_Step *)can_load_sequence, COUNT(can_load_sequence));
873
     execute_extruder_sequence((const E_Step *)can_load_sequence, COUNT(can_load_sequence));
681
 
874
 
682
     int filament_detected_count = 0;
875
     int filament_detected_count = 0;
683
-    const int steps = MMU2_CAN_LOAD_RETRACT / MMU2_CAN_LOAD_INCREMENT;
876
+    const int steps = (MMU2_CAN_LOAD_RETRACT) / (MMU2_CAN_LOAD_INCREMENT);
684
     DEBUG_ECHOLNPGM("MMU can_load:");
877
     DEBUG_ECHOLNPGM("MMU can_load:");
685
     LOOP_L_N(i, steps) {
878
     LOOP_L_N(i, steps) {
686
       execute_extruder_sequence((const E_Step *)can_load_increment_sequence, COUNT(can_load_increment_sequence));
879
       execute_extruder_sequence((const E_Step *)can_load_increment_sequence, COUNT(can_load_increment_sequence));
689
       if (mmu2s_triggered) ++filament_detected_count;
882
       if (mmu2s_triggered) ++filament_detected_count;
690
     }
883
     }
691
 
884
 
692
-    if (filament_detected_count <= steps - (MMU2_CAN_LOAD_DEVIATION / MMU2_CAN_LOAD_INCREMENT)) {
885
+    if (filament_detected_count <= steps - (MMU2_CAN_LOAD_DEVIATION) / (MMU2_CAN_LOAD_INCREMENT)) {
693
       DEBUG_ECHOLNPGM(" failed.");
886
       DEBUG_ECHOLNPGM(" failed.");
694
       return false;
887
       return false;
695
     }
888
     }
702
 #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
895
 #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
703
 
896
 
704
   // Load filament into MMU2
897
   // Load filament into MMU2
705
-  void MMU2::load_filament(uint8_t index) {
898
+  void MMU2::load_filament(const uint8_t index) {
706
     if (!enabled) return;
899
     if (!enabled) return;
707
     command(MMU_CMD_L0 + index);
900
     command(MMU_CMD_L0 + index);
708
     manage_response(false, false);
901
     manage_response(false, false);
714
    * Switch material and load to nozzle
907
    * Switch material and load to nozzle
715
    *
908
    *
716
    */
909
    */
717
-  bool MMU2::load_filament_to_nozzle(uint8_t index) {
910
+  bool MMU2::load_filament_to_nozzle(const uint8_t index) {
718
 
911
 
719
     if (!enabled) return false;
912
     if (!enabled) return false;
720
 
913
 
739
   }
932
   }
740
 
933
 
741
   /**
934
   /**
742
-   *
743
    * Load filament to nozzle of multimaterial printer
935
    * Load filament to nozzle of multimaterial printer
744
    *
936
    *
745
    * This function is used only only after T? (user select filament) and M600 (change filament).
937
    * This function is used only only after T? (user select filament) and M600 (change filament).
751
     execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
943
     execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence));
752
   }
944
   }
753
 
945
 
754
-  bool MMU2::eject_filament(uint8_t index, bool recover) {
946
+  bool MMU2::eject_filament(const uint8_t index, const bool recover) {
755
 
947
 
756
     if (!enabled) return false;
948
     if (!enabled) return false;
757
 
949
 
798
   }
990
   }
799
 
991
 
800
   /**
992
   /**
801
-   *
802
-   * unload from hotend and retract to MMU
803
-   *
993
+   * Unload from hotend and retract to MMU
804
    */
994
    */
805
   bool MMU2::unload() {
995
   bool MMU2::unload() {
806
 
996
 

+ 11
- 7
Marlin/src/feature/mmu2/mmu2.h View File

44
   static void init();
44
   static void init();
45
   static void reset();
45
   static void reset();
46
   static void mmu_loop();
46
   static void mmu_loop();
47
-  static void tool_change(uint8_t index);
47
+  static void tool_change(const uint8_t index);
48
   static void tool_change(const char* special);
48
   static void tool_change(const char* special);
49
   static uint8_t get_current_tool();
49
   static uint8_t get_current_tool();
50
-  static void set_filament_type(uint8_t index, uint8_t type);
50
+  static void set_filament_type(const uint8_t index, const uint8_t type);
51
 
51
 
52
   #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
52
   #if BOTH(HAS_LCD_MENU, MMU2_MENUS)
53
     static bool unload();
53
     static bool unload();
54
     static void load_filament(uint8_t);
54
     static void load_filament(uint8_t);
55
     static void load_all();
55
     static void load_all();
56
-    static bool load_filament_to_nozzle(uint8_t index);
57
-    static bool eject_filament(uint8_t index, bool recover);
56
+    static bool load_filament_to_nozzle(const uint8_t index);
57
+    static bool eject_filament(const uint8_t index, const bool recover);
58
   #endif
58
   #endif
59
 
59
 
60
 private:
60
 private:
61
   static bool rx_str_P(const char* str);
61
   static bool rx_str_P(const char* str);
62
   static void tx_str_P(const char* str);
62
   static void tx_str_P(const char* str);
63
-  static void tx_printf_P(const char* format, int argument);
64
-  static void tx_printf_P(const char* format, int argument1, int argument2);
63
+  static void tx_printf_P(const char* format, const int argument);
64
+  static void tx_printf_P(const char* format, const int argument1, const int argument2);
65
   static void clear_rx_buffer();
65
   static void clear_rx_buffer();
66
 
66
 
67
   static bool rx_ok();
67
   static bool rx_ok();
89
     FORCE_INLINE static bool load_to_gears() { return true; }
89
     FORCE_INLINE static bool load_to_gears() { return true; }
90
   #endif
90
   #endif
91
 
91
 
92
+  #if ENABLED(MMU_EXTRUDER_SENSOR)
93
+    static void mmu_continue_loading();
94
+  #endif
95
+
92
   static bool enabled, ready, mmu_print_saved;
96
   static bool enabled, ready, mmu_print_saved;
93
 
97
 
94
   static uint8_t cmd, cmd_arg, last_cmd, extruder;
98
   static uint8_t cmd, cmd_arg, last_cmd, extruder;
96
   static volatile int8_t finda;
100
   static volatile int8_t finda;
97
   static volatile bool finda_runout_valid;
101
   static volatile bool finda_runout_valid;
98
   static int16_t version, buildnr;
102
   static int16_t version, buildnr;
99
-  static millis_t last_request, next_P0_request;
103
+  static millis_t prev_request, prev_P0_request;
100
   static char rx_buffer[MMU_RX_SIZE], tx_buffer[MMU_TX_SIZE];
104
   static char rx_buffer[MMU_RX_SIZE], tx_buffer[MMU_TX_SIZE];
101
 
105
 
102
   static inline void set_runout_valid(const bool valid) {
106
   static inline void set_runout_valid(const bool valid) {

+ 7
- 5
Marlin/src/inc/SanityCheck.h View File

2742
  * Prusa MMU2 requirements
2742
  * Prusa MMU2 requirements
2743
  */
2743
  */
2744
 #if ENABLED(PRUSA_MMU2)
2744
 #if ENABLED(PRUSA_MMU2)
2745
-  #if DISABLED(NOZZLE_PARK_FEATURE)
2746
-    #error "PRUSA_MMU2 requires NOZZLE_PARK_FEATURE."
2747
-  #elif EXTRUDERS != 5
2745
+  #if EXTRUDERS != 5
2748
     #error "PRUSA_MMU2 requires EXTRUDERS = 5."
2746
     #error "PRUSA_MMU2 requires EXTRUDERS = 5."
2749
-  #elif ENABLED(PRUSA_MMU2_S_MODE) && DISABLED(FILAMENT_RUNOUT_SENSOR)
2750
-    #error "PRUSA_MMU2_S_MODE requires FILAMENT_RUNOUT_SENSOR. Enable it to continue."
2747
+  #elif DISABLED(NOZZLE_PARK_FEATURE)
2748
+    #error "PRUSA_MMU2 requires NOZZLE_PARK_FEATURE. Enable it to continue."
2749
+  #elif EITHER(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR) && DISABLED(FILAMENT_RUNOUT_SENSOR)
2750
+    #error "PRUSA_MMU2_S_MODE or MMU_EXTRUDER_SENSOR requires FILAMENT_RUNOUT_SENSOR. Enable it to continue."
2751
+  #elif BOTH(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR)
2752
+    #error "Enable only one of PRUSA_MMU2_S_MODE or MMU_EXTRUDER_SENSOR."
2751
   #elif DISABLED(ADVANCED_PAUSE_FEATURE)
2753
   #elif DISABLED(ADVANCED_PAUSE_FEATURE)
2752
     static_assert(nullptr == strstr(MMU2_FILAMENT_RUNOUT_SCRIPT, "M600"), "ADVANCED_PAUSE_FEATURE is required to use M600 with PRUSA_MMU2.");
2754
     static_assert(nullptr == strstr(MMU2_FILAMENT_RUNOUT_SCRIPT, "M600"), "ADVANCED_PAUSE_FEATURE is required to use M600 with PRUSA_MMU2.");
2753
   #endif
2755
   #endif

+ 6
- 5
Marlin/src/lcd/language/language_fr.h View File

476
   PROGMEM Language_Str MSG_LCD_PROBING_FAILED              = _UxGT("Echec sonde");
476
   PROGMEM Language_Str MSG_LCD_PROBING_FAILED              = _UxGT("Echec sonde");
477
   PROGMEM Language_Str MSG_M600_TOO_COLD                   = _UxGT("M600: Trop froid");
477
   PROGMEM Language_Str MSG_M600_TOO_COLD                   = _UxGT("M600: Trop froid");
478
 
478
 
479
+  PROGMEM Language_Str MSG_KILL_MMU2_FIRMWARE              = _UxGT("MAJ firmware MMU!!");
479
   PROGMEM Language_Str MSG_MMU2_CHOOSE_FILAMENT_HEADER     = _UxGT("CHOISIR FILAMENT");
480
   PROGMEM Language_Str MSG_MMU2_CHOOSE_FILAMENT_HEADER     = _UxGT("CHOISIR FILAMENT");
480
   PROGMEM Language_Str MSG_MMU2_MENU                       = _UxGT("MMU");
481
   PROGMEM Language_Str MSG_MMU2_MENU                       = _UxGT("MMU");
481
   PROGMEM Language_Str MSG_MMU2_NOT_RESPONDING             = _UxGT("MMU ne répond plus");
482
   PROGMEM Language_Str MSG_MMU2_NOT_RESPONDING             = _UxGT("MMU ne répond plus");
482
-  PROGMEM Language_Str MSG_MMU2_RESUME                     = _UxGT("Continuer impr.");
483
-  PROGMEM Language_Str MSG_MMU2_RESUMING                   = _UxGT("Reprise...");
484
-  PROGMEM Language_Str MSG_MMU2_LOAD_FILAMENT              = _UxGT("Charger filament");
485
-  PROGMEM Language_Str MSG_MMU2_LOAD_ALL                   = _UxGT("Charger tous");
483
+  PROGMEM Language_Str MSG_MMU2_RESUME                     = _UxGT("Continuer Imp. MMU");
484
+  PROGMEM Language_Str MSG_MMU2_RESUMING                   = _UxGT("Reprise MMU...");
485
+  PROGMEM Language_Str MSG_MMU2_LOAD_FILAMENT              = _UxGT("Charge dans MMU");
486
+  PROGMEM Language_Str MSG_MMU2_LOAD_ALL                   = _UxGT("Charger tous dans MMU");
486
   PROGMEM Language_Str MSG_MMU2_LOAD_TO_NOZZLE             = _UxGT("Charger dans buse");
487
   PROGMEM Language_Str MSG_MMU2_LOAD_TO_NOZZLE             = _UxGT("Charger dans buse");
487
-  PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT             = _UxGT("Ejecter filament");
488
+  PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT             = _UxGT("Ejecter fil. du MMU");
488
   PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT_N           = _UxGT("Ejecter fil. ~");
489
   PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT_N           = _UxGT("Ejecter fil. ~");
489
   PROGMEM Language_Str MSG_MMU2_UNLOAD_FILAMENT            = _UxGT("Retrait filament");
490
   PROGMEM Language_Str MSG_MMU2_UNLOAD_FILAMENT            = _UxGT("Retrait filament");
490
   PROGMEM Language_Str MSG_MMU2_LOADING_FILAMENT           = _UxGT("Chargem. fil. %i...");
491
   PROGMEM Language_Str MSG_MMU2_LOADING_FILAMENT           = _UxGT("Chargem. fil. %i...");

Loading…
Cancel
Save