MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.18k stars 19.21k forks source link

[FR] (Additional Realtime commands for Marlin) #19253

Closed fedetony closed 3 years ago

fedetony commented 4 years ago

Description

For CNC, laser and Drawing bots its important the machine reacts immediately. For example long slow movements in a CNC normally can be paused and resumed by interrupting the command in the middle of the process. The interruption is almost instant, in Marlin one must wait until the command is fulfilled to pause(M0-M1). At the moment, the only possibility is to stop the process, in Marlin is through Emergency stop (M112) and/or Stop (M410) working with the emergency parser. It would be nice to have Pause/Resume and report (M114) operational in a similar way. Any process can be interrupted/queried at any point of a process by the host.

Feature Workflow

When Command M0,M1 is given, System pauses immediately (I mean in the middle of a command , not to wait until last command is fully executed). When M108 is entered the system continues where it was. Also a Soft RESET would be a nice feature to have if it is functional after an M112 command. M114 should report instantly with position and marlin_state variable.

Additional Information

Grbl behaves in this way with the commands: '?' -> sends position and state information immediately to the host '!' -> Holds feed immediately '~' ->Resumes Feed '^X' -> Soft reset

Is very well described in Grbl documentation: A realtime command: Will execute within tens of milliseconds. Is a single character that may be sent at any time. Does not require a line feed or carriage return after them. Is not considered a part of the streaming protocol. Are intercepted when they are received and never placed in a buffer to be parsed. Will ignore multiple commands until it has executed the first received command. May be tied to an input pin and may be operated with a button or switch. Actions depends on state or what Machine_state is doing. It may not do anything.

thisiskeithb commented 4 years ago

There's an open PR with this feature: https://github.com/MarlinFirmware/Marlin/pull/17462

Also from the comments:

Instant stop from 60mm/s to zero is going to lose steps, and instant start at that speed will also lose steps. Both can be potentially damaging to hardware. TMC driver models that have StandStill detection will go into shutdown and must be reset. It is not likely in most cases that a job could be resumed after stopping with this method.

GMagician commented 4 years ago

@thisiskeithb I think that, as for all industrial machines, hold is meant to stop with ramp, not abruptly

thisiskeithb commented 4 years ago

There is a comment in that PR about a ramp down, but it might get traction again if you leave a comment 🙂

fedetony commented 4 years ago

I have been thinking how to implement it.My idea is to store the command issued, buffer and current position in memory. Then a stop command can be issued(M410) or quickstop_stepper(); which works just fine, just it clears the buffer. When resumed the buffer will be restated and the command/process restated. If stopped then buffer clears. Added this function to motion.cpp to report while moving. I call it from emergency parser and works fine:

/**
 * Output the current position (processed) to serial while moving
 */
void report_current_position_moving() {

  get_cartesian_from_steppers();
  const xyz_pos_t lpos = cartes.asLogical();
  SERIAL_ECHOPAIR("X:", lpos.x, " Y:", lpos.y, " Z:", lpos.z, " E:", current_position.e);

  stepper.report_positions();
  #if IS_SCARA
    scara_report_positions();
  #endif
  report_current_grblstate_moving(); 
}
/**
 * Output the current grbl compatible state to serial while moving
 */
void report_current_grblstate_moving() {
  #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
    SERIAL_ECHOPAIR("S_XYZ:", marlin_state);
    SERIAL_EOL();
  #endif  
}
fedetony commented 4 years ago

Ok took me less time that I imagined, take in count please I've only seen Marlin for 1 week, yet is so well structured that is easy to find the programming. Marlin_ModifiedPauseresume.zip

I modified all the files enclosed in the Zip file and It pause and resumes without much issue. I did not change the Parser.cpp so after returning from the Command it shows "unknown command" messages for all commands written (easy to change). The emergency parser commands are: P to quick pause, R to quick resume and S to print status while moving or processing. Modified the keep_alive routine to constantly give the position information and not only a busy message. Is activated by FULL_REPORT_TO_HOST_FEATURE I've added to the configuation.h.

Hope it helps :)

Here a test run:

G28 X

S_XYZ:9
echo:busy: processing
X:0.0000 Y:600.0000 Z:85.0000 E:0.0000 Count X:0 Y:60000 Z:34000
S_XYZ:9
echo:busy: processing
X:0.8925 Y:600.0000 Z:85.0000 E:0.0000 Count X:357 Y:60000 Z:34000
S_XYZ:9
echo:busy: processing
X:3.4500 Y:600.0000 Z:85.0000 E:0.0000 Count X:1381 Y:60000 Z:34000
S_XYZ:9
echo:busy: processing
X:5.9475 Y:600.0000 Z:85.0000 E:0.0000 Count X:2380 Y:60000 Z:34000
S_XYZ:9
echo:busy: processing
X:8.4450 Y:600.0000 Z:85.0000 E:0.0000 Count X:3379 Y:60000 Z:34000
S_XYZ:9
X:700.0000 Y:600.0000 Z:85.0000 E:0.0000 Count X:280800 Y:60000 Z:34000
Z_move_comp
S_XYZ:3
ok P13 B2
G1 X100

S_XYZ:5
echo:busy: processing
X:677.7575 Y:600.0000 Z:85.0000 E:0.0000 Count X:271096 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:652.7975 Y:600.0000 Z:85.0000 E:0.0000 Count X:261113 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:627.8375 Y:600.0000 Z:85.0000 E:0.0000 Count X:251129 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:602.8775 Y:600.0000 Z:85.0000 E:0.0000 Count X:241145 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:577.9175 Y:600.0000 Z:85.0000 E:0.0000 Count X:231161 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:552.9575 Y:600.0000 Z:85.0000 E:0.0000 Count X:221176 Y:60000 Z:34000
S_XYZ:5

P
echo:busy: processing
X:527.9975 Y:600.0000 Z:85.0000 E:0.0000 Count X:211192 Y:60000 Z:34000
S_XYZ:5

S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:516.5400 Y:600.0000 Z:85.0000 E:0.0000 Count X:206616 Y:60000 Z:34000
S_XYZ:6
R

S_XYZ:5
echo:busy: processing
X:509.5250 Y:600.0000 Z:85.0000 E:0.0000 Count X:203804 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:484.5650 Y:600.0000 Z:85.0000 E:0.0000 Count X:193819 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:459.6050 Y:600.0000 Z:85.0000 E:0.0000 Count X:183838 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:434.6450 Y:600.0000 Z:85.0000 E:0.0000 Count X:173851 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:408.9875 Y:600.0000 Z:85.0000 E:0.0000 Count X:163589 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:384.0500 Y:600.0000 Z:85.0000 E:0.0000 Count X:153614 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:359.0900 Y:600.0000 Z:85.0000 E:0.0000 Count X:143629 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:334.1300 Y:600.0000 Z:85.0000 E:0.0000 Count X:133645 Y:60000 Z:34000
S_XYZ:5
P

S_XYZ:6
echo:busy: processing
X:315.3575 Y:600.0000 Z:85.0000 E:0.0000 Count X:126143 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:315.3575 Y:600.0000 Z:85.0000 E:0.0000 Count X:126143 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:315.3575 Y:600.0000 Z:85.0000 E:0.0000 Count X:126143 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:315.3575 Y:600.0000 Z:85.0000 E:0.0000 Count X:126143 Y:60000 Z:34000
S_XYZ:6
echo:busy: processing
X:315.3575 Y:600.0000 Z:85.0000 E:0.0000 Count X:126143 Y:60000 Z:34000
S_XYZ:6
R

S_XYZ:5
echo:busy: processing
X:312.1400 Y:600.0000 Z:85.0000 E:0.0000 Count X:124850 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:287.1800 Y:600.0000 Z:85.0000 E:0.0000 Count X:114866 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:262.2200 Y:600.0000 Z:85.0000 E:0.0000 Count X:104882 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:237.2600 Y:600.0000 Z:85.0000 E:0.0000 Count X:94898 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:212.3000 Y:600.0000 Z:85.0000 E:0.0000 Count X:84913 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:187.3400 Y:600.0000 Z:85.0000 E:0.0000 Count X:74930 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:162.3800 Y:600.0000 Z:85.0000 E:0.0000 Count X:64945 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:137.0000 Y:600.0000 Z:85.0000 E:0.0000 Count X:54795 Y:60000 Z:34000
S_XYZ:5
echo:busy: processing
X:112.0600 Y:600.0000 Z:85.0000 E:0.0000 Count X:44818 Y:60000 Z:34000
S_XYZ:5
Z_move_comp
X:100.0000 Y:600.0000 Z:85.0000 E:0.0000 Count X:40000 Y:60000 Z:34000
S_XYZ:3
ok P15 B0
echo:Unknown command: "P"
ok P15 B0
echo:Unknown command: "R"
ok P15 B1
echo:Unknown command: "P"
ok P15 B2
echo:Unknown command: "R"
ok P15 B3
AnHardt commented 4 years ago

Pleas try:

M117 SHOWSTOPPER

somewhere in a g-code script. Any reaction of your new additions would be a showstopper.

Please use git or at least provide diffs. Reviewing your code from the .zip is a pain.

fedetony commented 4 years ago

Pleas try:

M117 SHOWSTOPPER

somewhere in a g-code script. Any reaction of your new additions would be a showstopper.

Please use git or at least provide diffs. Reviewing your code from the .zip is a pain.

Sorry, I'm new to this. Please let me know how (or give me a link where I can find how to) add to git? You can compare the files with a compare tool as tortoise.

The M117 issue is that I used S, R and P for codes, since I was just trying out that the functions would work.
Same as
M117 LCR Print M112

It needs to be modified to an actual code as M000 or something it will not interfere with normal text and commands. Attached adapted the e_parser.h for P000 for quick pause R000 for quick Resume and S000 to show position moving.

e_parser.zip

fedetony commented 4 years ago

@AnHardt So Downloaded the repository again, made a git init then replaced my folder with all changes, staged and commit them adding the correspondent comments on my local directory. Here git diff. using git diff 9913333c33d234264a9072630e8b5ffbf07bad7e f4933bff4c1b30b1d69c35277ed1591e261f32db last commit hash on repository on github. I have not git push since I do not know if it will rewrite the Marlin repository and I do not want to damage the files (I'm very new to this, first time using git). I am not even a software developer... so please be a bit patient with me :)


 #
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 8cd2faf7f..beb62ed7c 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -71,7 +71,7 @@
 // @section homing

@@ -1493,9 +1494,10 @@
 // every couple of seconds when it can't accept commands.
 //
 #define HOST_KEEPALIVE_FEATURE        // Disable this if your host doesn't like keepalive messages
-#define DEFAULT_KEEPALIVE_INTERVAL 2  // Number of seconds between "busy" messages. Set with M113.
+#define DEFAULT_KEEPALIVE_INTERVAL 1  // Number of seconds between "busy" messages. Set with M113.
+#define KEEPALIVE_INTERVAL_DIVIDER 3 // Divide the KEEPALIVE_INTERVAL for faster reporting
 #define BUSY_WHILE_HEATING            // Some hosts require "busy" messages even during heating
-
+#define FULL_REPORT_TO_HOST_FEATURE        // Enable this to send Machine status reports while moving and status reports GRBL style

 // Host Receive Buffer Size
 // Without XON/XOFF flow control (see SERIAL_XON_XOFF below) 32 bytes should be enough.
@@ -1908,7 +1908,7 @@
  * Currently handles M108, M112, M410, M876
  * NOTE: Not yet implemented for all platforms.
  */
-//#define EMERGENCY_PARSER
+#define EMERGENCY_PARSER

 // Some clients will have this feature soon. This could make the NO_TIMEOUTS unnecessary.
-//#define ADVANCED_OK
+#define ADVANCED_OK

 // Printrun may have trouble receiving long strings all at once.
 // This option inserts short delays between lines of serial output.
 #define SERIAL_OVERRUN_PROTECTION

 // @section extras
 /**
  * G-code Macros
@@ -3224,9 +3224,9 @@
  * Host Prompt Support enables Marlin to use the host for user prompts so
  * filament runout and other processes can be managed from the host side.
  */
-//#define HOST_ACTION_COMMANDS
+#define HOST_ACTION_COMMANDS
 #if ENABLED(HOST_ACTION_COMMANDS)
-  //#define HOST_PROMPT_SUPPORT
+  #define HOST_PROMPT_SUPPORT
 #endif

 /**
@@ -3376,9 +3376,9 @@
  * string to enable synchronization with DLP projector exposure. This change will allow to use
  * [[WaitForDoneMessage]] instead of populating your gcode with M400 commands
  */
-//#define NANODLP_Z_SYNC
+#define NANODLP_Z_SYNC
 #if ENABLED(NANODLP_Z_SYNC)
-  //#define NANODLP_ALL_AXIS  // Enables "Z_move_comp" output on any axis move.
+  #define NANODLP_ALL_AXIS  // Enables "Z_move_comp" output on any axis move.
                               // Default behavior is limited to Z axis only.
 #endif

diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp
index e703eaf8d..b20b4b86f 100644
--- a/Marlin/src/MarlinCore.cpp
+++ b/Marlin/src/MarlinCore.cpp
@@ -236,6 +236,8 @@ PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMST

 MarlinState marlin_state = MF_INITIALIZING;

+M_StateEnum M_State_grbl = M_INIT;
+
 // For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
 bool wait_for_heatup = true;

@@ -341,6 +343,15 @@ void quickstop_stepper() {
   sync_plan_position();
 }

+void quickpause_stepper() {
+  planner.quick_pause();
+  //planner.synchronize();
+}
+void quickresume_stepper() {
+  planner.quick_resume();
+  //planner.synchronize();
+}
+
 void enable_e_steppers() {
   #define _ENA_E(N) ENABLE_AXIS_E##N();
   REPEAT(E_STEPPERS, _ENA_E)
diff --git a/Marlin/src/MarlinCore.h b/Marlin/src/MarlinCore.h
index 69afc7f30..c51ef218e 100644
--- a/Marlin/src/MarlinCore.h
+++ b/Marlin/src/MarlinCore.h
@@ -60,6 +60,8 @@ void kill(PGM_P const lcd_error=nullptr, PGM_P const lcd_component=nullptr, cons
 void minkill(const bool steppers_off=false);

 void quickstop_stepper();
+void quickpause_stepper();
+void quickresume_stepper();

 // Global State of the firmware
 enum MarlinState : uint8_t {
@@ -76,6 +78,8 @@ extern MarlinState marlin_state;
 inline bool IsRunning() { return marlin_state == MF_RUNNING; }
 inline bool IsStopped() { return marlin_state != MF_RUNNING; }

+extern M_StateEnum M_State_grbl;
+
 bool printingIsActive();
 bool printingIsPaused();
 void startOrResumeJob();
diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h
index a5b78caab..dd67ac6dc 100644
--- a/Marlin/src/core/types.h
+++ b/Marlin/src/core/types.h
@@ -29,6 +29,32 @@
 class __FlashStringHelper;
 typedef const __FlashStringHelper *progmem_str;

+//
+// Enumerated Status indices
+//
+//  Coding as GRBL or TinyG for Machine states
+//      0      machine is initializing
+//      1      machine is ready for use
+//      2      machine is in alarm state (soft shut down)
+//      3      program stop or no more blocks (M0, M1, M60)
+//      4      program end via M2, M30
+//      5      motion is running
+//      6      motion is holding
+//      7      probe cycle active
+//      8      machine is running (cycling)
+//      9      machine is homing
+//      10     machine is jogging
+//      11     machine is in hard alarm state (shut down)
+//
+//        #1=reset, 2=alarm, 3=idle, 4=end, 5=run, 6=hold, 7=probe, 8=cycling,  9=homing, 10 =jogging 11=error
+//
+enum M_StateEnum : uint8_t {
+  M_INIT   = 0,   M_RESET = 1,  M_ALARM   = 2,   M_IDLE   = 3,
+  M_END   = 4,  M_RUNNING = 5,   M_HOLD = 6,  M_PROBE  = 7,
+  M_CYCLING  = 8,  M_HOMING  = 9,  M_JOGGING  = 10,  M_ERROR  = 11
+};
+
+
 //
 // Enumerated axis indices
 //
diff --git a/Marlin/src/feature/e_parser.h b/Marlin/src/feature/e_parser.h
index 8d11463ec..e5b6ac23a 100644
--- a/Marlin/src/feature/e_parser.h
+++ b/Marlin/src/feature/e_parser.h
@@ -27,6 +27,7 @@

 #include "../inc/MarlinConfigPre.h"

+
 #if ENABLED(HOST_PROMPT_SUPPORT)
   #include "host_actions.h"
 #endif
@@ -34,12 +35,16 @@
 // External references
 extern bool wait_for_user, wait_for_heatup;
 void quickstop_stepper();
+void quickpause_stepper();
+void quickresume_stepper();
+void report_current_position_moving();

 class EmergencyParser {

 public:

   // Currently looking for: M108, M112, M410, M876
+  // S000 STATE , P000 for Pause, R000 for resume
   enum State : char {
     EP_RESET,
     EP_N,
@@ -52,6 +57,18 @@ public:
     EP_M4,
     EP_M41,
     EP_M410,
+    EP_S,
+    EP_S0,
+    EP_S00,
+    EP_R,
+    EP_R0,
+    EP_R00,
+    EP_P,
+    EP_P0,
+    EP_P00,
+    EP_grblSTATUS,
+    EP_grblPAUSE,
+    EP_grblRESUME,
     #if ENABLED(HOST_PROMPT_SUPPORT)
       EP_M8,
       EP_M87,
@@ -82,6 +99,9 @@ public:
           case ' ': case '\n': case '\r': break;
           case 'N': state = EP_N;      break;
           case 'M': state = EP_M;      break;
+          case 'S': state = EP_S;      break;
+          case 'P': state = EP_P;      break;
+          case 'R': state = EP_R;      break;
           default: state  = EP_IGNORE;
         }
         break;
@@ -96,7 +116,60 @@ public:
           default:  state = EP_IGNORE;
         }
         break;
-
+      case EP_S:
+        switch (c) {
+          case '0': state = EP_S0;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_S0:
+        switch (c) {
+          case '0': state = EP_S00;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_S00:
+        switch (c) {
+          case '0': state = EP_grblSTATUS;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_R:
+        switch (c) {
+          case '0': state = EP_R0;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_R0:
+        switch (c) {
+          case '0': state = EP_R00;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_R00:
+        switch (c) {
+          case '0': state = EP_grblRESUME;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_P:
+        switch (c) {
+          case '0': state = EP_P0;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_P0:
+        switch (c) {
+          case '0': state = EP_P00;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
+      case EP_P00:
+        switch (c) {
+          case '0': state = EP_grblPAUSE;   break;
+          default:  state = EP_IGNORE;
+        }
+        break;
       case EP_M:
         switch (c) {
           case ' ': break;
@@ -177,6 +250,9 @@ public:
             #if ENABLED(HOST_PROMPT_SUPPORT)
               case EP_M876SN: host_response_handler(M876_reason); break;
             #endif
+            case EP_grblSTATUS: report_current_position_moving(); break;
+            case EP_grblPAUSE: quickpause_stepper(); break;
+            case EP_grblRESUME: quickresume_stepper(); break;
             default: break;
           }
           state = EP_RESET;
diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp
index e7651cc74..d52f69548 100644
--- a/Marlin/src/gcode/bedlevel/abl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp
@@ -163,7 +163,8 @@
  *
  */
 G29_TYPE GcodeSuite::G29() {
-
+  M_State_grbl=M_PROBE;
+  report_current_grblstate_moving();
   reset_stepper_timeout();

   const bool seenQ = EITHER(DEBUG_LEVELING_FEATURE, PROBE_MANUALLY) && parser.seen('Q');
@@ -899,6 +900,8 @@ G29_TYPE GcodeSuite::G29() {
   report_current_position();

   G29_RETURN(isnan(measured_z));
+  M_State_grbl=M_IDLE;
+  report_current_grblstate_moving();
 }

 #endif // HAS_ABL_NOT_UBL
diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
index 68ac459eb..8767a6179 100644
--- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
@@ -60,7 +60,8 @@ inline void echo_not_entered(const char c) { SERIAL_CHAR(c); SERIAL_ECHOLNPGM("
  *
  */
 void GcodeSuite::G29() {
-
+  M_State_grbl=M_PROBE;
+  report_current_grblstate_moving();
   static int mbl_probe_index = -1;
   TERN_(HAS_SOFTWARE_ENDSTOPS, static bool saved_soft_endstops_state);

@@ -197,6 +198,8 @@ void GcodeSuite::G29() {
   }

   report_current_position();
+  M_State_grbl=M_IDLE;
+  report_current_grblstate_moving();
 }

 #endif // MESH_BED_LEVELING
diff --git a/Marlin/src/gcode/bedlevel/ubl/G29.cpp b/Marlin/src/gcode/bedlevel/ubl/G29.cpp
index 2ef3ab4ce..9e7fdb354 100644
--- a/Marlin/src/gcode/bedlevel/ubl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/ubl/G29.cpp
@@ -31,6 +31,11 @@
 #include "../../gcode.h"
 #include "../../../feature/bedlevel/bedlevel.h"

-void GcodeSuite::G29() { ubl.G29(); }
+void GcodeSuite::G29() {
+M_State_grbl=M_PROBE;
+  report_current_grblstate_moving();
+  ubl.G29();
+  M_State_grbl=M_IDLE;
+  report_current_grblstate_moving(); }

 #endif // AUTO_BED_LEVELING_UBL
diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp
index 0e1f70789..843982e3f 100644
--- a/Marlin/src/gcode/calibrate/G28.cpp
+++ b/Marlin/src/gcode/calibrate/G28.cpp
@@ -202,6 +202,9 @@ void GcodeSuite::G28() {

   TERN_(DWIN_CREALITY_LCD, HMI_flag.home_flag = true);

+  M_State_grbl=M_HOMING;
+  report_current_grblstate_moving();
+
   #if ENABLED(DUAL_X_CARRIAGE)
     bool IDEX_saved_duplication_state = extruder_duplication_enabled;
     DualXMode IDEX_saved_mode = dual_x_carriage_mode;
@@ -478,4 +481,6 @@ void GcodeSuite::G28() {
       L64xxManager.set_param((L64XX_axis_t)cv, L6470_ABS_POS, stepper.position(L64XX_axis_xref[cv]));
     }
   #endif
+  M_State_grbl=M_IDLE;
+  report_current_grblstate_moving();
 }
diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp
index 53af04d52..ac9799127 100644
--- a/Marlin/src/gcode/calibrate/G33.cpp
+++ b/Marlin/src/gcode/calibrate/G33.cpp
@@ -384,7 +384,8 @@ static float auto_tune_a() {
  *   E   Engage the probe for each point
  */
 void GcodeSuite::G33() {
-
+  M_State_grbl=M_PROBE;
+  report_current_grblstate_moving();
   const int8_t probe_points = parser.intval('P', DELTA_CALIBRATION_DEFAULT_POINTS);
   if (!WITHIN(probe_points, 0, 10)) {
     SERIAL_ECHOLNPGM("?(P)oints implausible (0-10).");
@@ -643,6 +644,8 @@ void GcodeSuite::G33() {
   while (((zero_std_dev < test_precision && iterations < 31) || iterations <= force_iterations) && zero_std_dev > calibration_precision);

   ac_cleanup(TERN_(HAS_MULTI_HOTEND, old_tool_index));
+  M_State_grbl=M_IDLE;
+  report_current_grblstate_moving();
 }

 #endif // DELTA_AUTO_CALIBRATION
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index c0a795025..627f8a197 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -84,6 +84,7 @@ uint8_t GcodeSuite::axis_relative = (
 #if ENABLED(HOST_KEEPALIVE_FEATURE)
   GcodeSuite::MarlinBusyState GcodeSuite::busy_state = NOT_BUSY;
   uint8_t GcodeSuite::host_keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
+  int GcodeSuite::host_keepalive_interval_divider= KEEPALIVE_INTERVAL_DIVIDER;
 #endif

 #if ENABLED(CNC_WORKSPACE_PLANES)
@@ -1017,18 +1018,33 @@ void GcodeSuite::process_subcommands_now(char * gcode) {
         case IN_HANDLER:
         case IN_PROCESS:
           SERIAL_ECHO_MSG(STR_BUSY_PROCESSING);
+          #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
+            report_current_position_moving();
+          #endif
           break;
         case PAUSED_FOR_USER:
           SERIAL_ECHO_MSG(STR_BUSY_PAUSED_FOR_USER);
+          M_State_grbl = M_HOLD;
+          report_current_grblstate_moving();
           break;
         case PAUSED_FOR_INPUT:
           SERIAL_ECHO_MSG(STR_BUSY_PAUSED_FOR_INPUT);
+          M_State_grbl = M_HOLD;
+          report_current_grblstate_moving();
           break;
         default:
           break;
       }
     }
-    next_busy_signal_ms = ms + SEC_TO_MS(host_keepalive_interval);
+    if (host_keepalive_interval_divider>0)
+      next_busy_signal_ms = ms + SEC_TO_MS(host_keepalive_interval)/host_keepalive_interval_divider;
+    else
+    {
+      /* code */
+      next_busy_signal_ms = ms + SEC_TO_MS(host_keepalive_interval);
+    }
+
+
   }

 #endif // HOST_KEEPALIVE_FEATURE
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 23bf2c0ce..b6525c3db 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -392,6 +392,7 @@ public:

     static MarlinBusyState busy_state;
     static uint8_t host_keepalive_interval;
+    static int host_keepalive_interval_divider;

     static void host_keepalive();

diff --git a/Marlin/src/gcode/host/M114.cpp b/Marlin/src/gcode/host/M114.cpp
index 85a38f646..799462136 100644
--- a/Marlin/src/gcode/host/M114.cpp
+++ b/Marlin/src/gcode/host/M114.cpp
@@ -181,6 +181,7 @@
     const xyze_float_t diff = from_steppers - leveled;
     SERIAL_ECHOPGM("Diff:   ");
     report_xyze(diff);
+    report_current_grblstate_moving();
   }

 #endif // M114_DETAIL
@@ -216,4 +217,5 @@ void GcodeSuite::M114() {

   TERN_(M114_LEGACY, planner.synchronize());
   report_current_position_projected();
+  report_current_grblstate_moving();
 }
diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp
index b6ddf9634..c63173d70 100644
--- a/Marlin/src/gcode/motion/G0_G1.cpp
+++ b/Marlin/src/gcode/motion/G0_G1.cpp
@@ -58,6 +58,8 @@ void GcodeSuite::G0_G1(
         | (parser.seen('Z') ? _BV(Z_AXIS) : 0) )
     #endif
   ) {
+    M_State_grbl=M_RUNNING;
+    report_current_grblstate_moving();

     #ifdef G0_FEEDRATE
       feedRate_t old_feedrate;
@@ -121,5 +123,11 @@ void GcodeSuite::G0_G1(
         SERIAL_ECHOLNPGM(STR_Z_MOVE_COMP);
       }
     #endif
+    #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
+      #if ENABLED(NANODLP_Z_SYNC)
+        M_State_grbl=M_IDLE;
+      #endif
+      report_current_position_moving();
+    #endif
   }
 }
diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp
index 59a534635..cbf6f8462 100644
--- a/Marlin/src/gcode/motion/G2_G3.cpp
+++ b/Marlin/src/gcode/motion/G2_G3.cpp
@@ -276,6 +276,8 @@ void plan_arc(
  */
 void GcodeSuite::G2_G3(const bool clockwise) {
   if (MOTION_CONDITIONS) {
+    M_State_grbl=M_RUNNING;
+    report_current_grblstate_moving();

     #if ENABLED(SF_ARC_FIX)
       const bool relative_mode_backup = relative_mode;
@@ -336,6 +338,11 @@ void GcodeSuite::G2_G3(const bool clockwise) {
     }
     else
       SERIAL_ERROR_MSG(STR_ERR_ARC_ARGS);
+
+    M_State_grbl=M_IDLE;
+    #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
+      report_current_position_moving();
+    #endif
   }
 }

diff --git a/Marlin/src/gcode/probe/G30.cpp b/Marlin/src/gcode/probe/G30.cpp
index 4347f55aa..2490609f7 100644
--- a/Marlin/src/gcode/probe/G30.cpp
+++ b/Marlin/src/gcode/probe/G30.cpp
@@ -44,7 +44,6 @@ void GcodeSuite::G30() {
                          parser.linearval('Y', current_position.y + probe.offset_xy.y) };

   if (!probe.can_reach(pos)) return;
-
   // Disable leveling so the planner won't mess with us
   TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));

diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp
index 401721140..53142a80b 100644
--- a/Marlin/src/module/motion.cpp
+++ b/Marlin/src/module/motion.cpp
@@ -228,6 +228,8 @@ void report_real_position() {
   report_more_positions();
 }

+
+
 // Report the logical current position according to the most recent G-code command
 void report_current_position() {
   report_logical_position(current_position);
@@ -245,6 +247,47 @@ void report_current_position_projected() {
   stepper.report_a_position(planner.position);
 }

+
+/**
+ * Output the current position (processed) to serial while moving
+ */
+void report_current_position_moving() {
+
+  get_cartesian_from_steppers();
+  const xyz_pos_t lpos = cartes.asLogical();
+  SERIAL_ECHOPAIR("X:", lpos.x, " Y:", lpos.y, " Z:", lpos.z, " E:", current_position.e);
+
+  stepper.report_positions();
+  #if IS_SCARA
+    scara_report_positions();
+  #endif
+  report_current_grblstate_moving();
+}
+/**
+ * Output the current grbl compatible state to serial while moving
+ */
+void report_current_grblstate_moving() {
+  #if ENABLED(FULL_REPORT_TO_HOST_FEATURE)
+    SERIAL_ECHOPAIR("S_XYZ:", M_State_grbl);
+    SERIAL_EOL();
+  #endif
+}
+/**
+ *  grbl compatible state to marlin_state
+ */
+void set_M_state_from_marlin_state() {
+  switch (marlin_state) {
+      case MF_INITIALIZING: M_State_grbl=M_INIT; break;
+      case MF_SD_COMPLETE: M_State_grbl=M_ALARM; break;
+      case MF_WAITING: M_State_grbl=M_IDLE; break;
+      case MF_STOPPED: M_State_grbl=M_END; break;
+      case MF_RUNNING: M_State_grbl=M_RUNNING; break;
+      case MF_PAUSED: M_State_grbl=M_HOLD; break;
+      case MF_KILLED: M_State_grbl=M_ERROR; break;
+      default: M_State_grbl=M_IDLE;
+  }
+}
+
 /**
  * sync_plan_position
  *
diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h
index c3f2d9b77..4e36d142d 100644
--- a/Marlin/src/module/motion.h
+++ b/Marlin/src/module/motion.h
@@ -166,6 +166,9 @@ typedef struct { xyz_pos_t min, max; } axis_limits_t;
 void report_real_position();
 void report_current_position();
 void report_current_position_projected();
+void report_current_position_moving();
+void report_current_grblstate_moving();
+void set_M_state_from_marlin_state();

 void get_cartesian_from_steppers();
 void set_current_from_steppers_for_axis(const AxisEnum axis);
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 931daa332..51fc7e214 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -1592,6 +1592,28 @@ void Planner::quick_stop() {
   // And stop the stepper ISR
   stepper.quick_stop();
 }
+void Planner::quick_pause() {
+
+  // Suspend until quick resume is called
+  // do not empty buffers or queues
+
+  const bool was_enabled = stepper.suspend();
+  if (was_enabled) {
+    M_State_grbl=M_HOLD;
+    report_current_grblstate_moving();
+
+  }
+
+}
+void Planner::quick_resume() {
+
+  // if Suspended resume
+  set_M_state_from_marlin_state();
+  report_current_grblstate_moving();
+  stepper.wake_up();
+
+}
+

 void Planner::endstop_triggered(const AxisEnum axis) {
   // Record stepper position and discard the current block
diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h
index f3a3a0e0f..3ef5e2d91 100644
--- a/Marlin/src/module/planner.h
+++ b/Marlin/src/module/planner.h
@@ -828,6 +828,10 @@ class Planner {
     // Called to force a quick stop of the machine (for example, when
     // a Full Shutdown is required, or when endstops are hit)
     static void quick_stop();
+    // Called to force a quick pause of the machine (for example, when
+    // a pause is required on the middle of movement)
+    static void quick_pause();
+    static void quick_resume();

     // Called when an endstop is triggered. Causes the machine to stop inmediately
     static void endstop_triggered(const AxisEnum axis);
fedetony commented 4 years ago

Pleas try:

M117 SHOWSTOPPER

somewhere in a g-code script. Any reaction of your new additions would be a showstopper.

Please use git or at least provide diffs. Reviewing your code from the .zip is a pain.

M117 SHOWSTOPPER

//action:notification SHOWSTOPPER

ok P15 B3
fedetony commented 4 years ago

18427 is quite similar to what is achieved here.

mron commented 4 years ago

I will contribute time to make this happen. I want to see it done reliably. No lost steps. No lost commands. Perfect command sync between CNC controller and Marlin.

IvanBayan commented 4 years ago

@fedetony First of all, thank you for your attempt to make real time pause/resume. I would like to suggest you to make a fork of that repo, and create your own branch from 2.0.x branch. You will be able to push code changes into your repository and use github's pull request functionality. I hope that guide will help you: https://gist.github.com/MarcDiethelm/7303312 BTW, M114 already has realtime report ability, check for M114_REALTIME

mron commented 4 years ago

I followed the guide and cloned Marlin. I'm struggling with VSC and plattformio. I'm not sure how to keep two projects separate. I have the Marlin that works on my CNC and the one I want to use to work on the Pause/Resume. Create a branch?

@fedetony I'd like to work on this as well. I think I understand your approach. Won't a quick_stop() lose steps?

fedetony commented 4 years ago

@IvanBayan Thank you for your comment. I've created the fork, pushed my changes, and made my first pull request. I'm not sure if I made a mistake since : All checks have failed. lol 🍡 @mron In my machine it does not loose any, yet it does not move too fast and has lead screws. This is to be tested in other machines. But is possible to recover:

P000 You pause abruptly
S000 Show actual position  (for checking)
M410 then you Stop the machine, 
R000 then resume (wakes the steppers), then 
M60 save position, 
G28 home sequence
M61 go back to position
mron commented 4 years ago

I'm pretty sure if you turn off the steppers, you've lost the true count. With lead screws, you're right, probably won't notice it, unless you do it a lot. The internal count becomes inaccurate. You'd need an encoder to verify your actual position. I'm going to look at how GRBL implemented "!". @IvanBayan I set M114_REALTIME in my Configuration_adv.h. I get immediate response, but the XYZ values don't change. They show the destination values. I'm looking for current position. What @fedetony implemented.

mron commented 4 years ago

Looks like most of GRBL "feed hold" stuff is in stepper.c

IvanBayan commented 4 years ago

@mron If hare any chance, that you compiled M114 real time support, but issued that gcode without R flag? It is not in documentation, but to get realtime report you need to issue 'M114 R' gcode

IvanBayan commented 4 years ago

@fedetony my bad, I suggested you to use wrong branch for your patch.

My cent about real time stop/resume command. It definitely should use ramp or s-curve for pause/resume. Immediate start/stop without ramp will lead to steps losses and vibration, it's not so noticeable on machines with lead screws but it still present. Moreover under the load or on high speeds step motors may not start motion at all. Without a doubt that functionality need much more time investment than using quickstop_stepper().

mron commented 4 years ago

I’m working on a smooth start/resume. I think I need to modify the planner and stepper code. I want to be very careful with that. I’m open to suggestions on how to proceed.

On Sep 12, 2020, at 11:25 AM, Ivan notifications@github.com wrote:

@fedetony https://github.com/fedetony my bad, I suggested you to use wrong branch for your patch.

My cent about real time stop/resume command. It definitely should use ramp or s-curve for pause/resume. Immediate start/stop without ramp will lead to steps losses and vibration, it's not so noticeable on machines with lead screws but it still present. Moreover under the load or on high speeds step motors may not start motion at all. Without a doubt that functionality need much more time investment than using quickstop_stepper().

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/19253#issuecomment-691527187, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABE67N57W2L5MOEUELSDKSDSFO4ITANCNFSM4QVQTP5A.

mron commented 4 years ago

as as M114 R. I tried this. I did not get current position. I got the position for the end of the current move. Maybe I needed other flags, of I’m using the wrong branch?

On Sep 12, 2020, at 12:02 PM, Ron Moreland ronmoreland@att.net wrote:

I’m working on a smooth start/resume. I think I need to modify the planner and stepper code. I want to be very careful with that. I’m open to suggestions on how to proceed.

On Sep 12, 2020, at 11:25 AM, Ivan <notifications@github.com mailto:notifications@github.com> wrote:

@fedetony https://github.com/fedetony my bad, I suggested you to use wrong branch for your patch.

My cent about real time stop/resume command. It definitely should use ramp or s-curve for pause/resume. Immediate start/stop without ramp will lead to steps losses and vibration, it's not so noticeable on machines with lead screws but it still present. Moreover under the load or on high speeds step motors may not start motion at all. Without a doubt that functionality need much more time investment than using quickstop_stepper().

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/19253#issuecomment-691527187, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABE67N57W2L5MOEUELSDKSDSFO4ITANCNFSM4QVQTP5A.

mron commented 4 years ago

I just tried it again. Works! I must have disabled it in the Config file at some point. It’s what I need to work on feed hold.

On Sep 12, 2020, at 12:04 PM, Ron Moreland ronmoreland@att.net wrote:

as as M114 R. I tried this. I did not get current position. I got the position for the end of the current move. Maybe I needed other flags, of I’m using the wrong branch?

On Sep 12, 2020, at 12:02 PM, Ron Moreland <ronmoreland@att.net mailto:ronmoreland@att.net> wrote:

I’m working on a smooth start/resume. I think I need to modify the planner and stepper code. I want to be very careful with that. I’m open to suggestions on how to proceed.

On Sep 12, 2020, at 11:25 AM, Ivan <notifications@github.com mailto:notifications@github.com> wrote:

@fedetony https://github.com/fedetony my bad, I suggested you to use wrong branch for your patch.

My cent about real time stop/resume command. It definitely should use ramp or s-curve for pause/resume. Immediate start/stop without ramp will lead to steps losses and vibration, it's not so noticeable on machines with lead screws but it still present. Moreover under the load or on high speeds step motors may not start motion at all. Without a doubt that functionality need much more time investment than using quickstop_stepper().

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/19253#issuecomment-691527187, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABE67N57W2L5MOEUELSDKSDSFO4ITANCNFSM4QVQTP5A.

AnHardt commented 4 years ago

A while ago i wrote down a concept for a deaccelerated fast stop. Maybe it can help.

mron commented 4 years ago

Thanks for responding. I read your concept. It’s along the lines of my thinking. One of the things that worried me were end conditions, trying to stop too close to the end of a line. There is a number of steps needed to stop and restart from the current velocity. If this is less than the remaining number of steps in a move, then let the move finish with a stop. Otherwise inject a stop.

I don’t understand the code well enough yet. I’m not a fast programmer and tend to be methodical. I’m currently testing the planner and stepper code and watching how it works. I hope to be injecting a stop and start today.

On Sep 12, 2020, at 3:14 PM, AnHardt notifications@github.com wrote:

A while ago i wrote down a concept for a deaccelerated fast stop https://github.com/AnHardt/Marlin/issues/87. Maybe it can help.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/19253#issuecomment-691560150, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABE67N7ER5WE2QDGRQMQ73LSFPXEDANCNFSM4QVQTP5A.

AnHardt commented 4 years ago

There is a number of steps needed to stop and restart from the current velocity. If this is less than the remaining number of steps in a move, then let the move finish with a stop.

Right. When a bufferline (aka segment) is running and its already behind the deacceleration point it will not stop in this segment when the following junction is not at zero (jerk) speed. But then there is always a next segment. For the last segment it's granted to end at zero speed.

But if there is a buffer full of short segments, what all together run only a few ms, that's not the case we worry about. We worry about the situation the buffer is full of long moves lasting together several seconds.

So if the break flag is set, simply ignore the deacceleration-point and always deaccelerate as much as possible (the info about how much is already in the buffer). If the segment ends just begin to run the next - immediately with the deaccelaration phase active. Until zero speed is reached. Then store the states.

mron commented 4 years ago

If I understand correctly, the deceleration point may have been calculated with another moves velocity in mind. Continuing to zero from that point might overshoot the correct endpoint. Recalculating a new deceleration point might cause more problems. Maybe if we’re decelerating, don’t insert. Let the next move start then drive it to zero.

On Sep 13, 2020, at 10:30 AM, AnHardt notifications@github.com wrote:

There is a number of steps needed to stop and restart from the current velocity. If this is less than the remaining number of steps in a move, then let the move finish with a stop.

Right. When a bufferline (aka segment) is running and its already behind the deacceleration point it will not stop in this segment when the following junction is not at zero (jerk) speed. But then there is always a next segment. For the last segment it's granted to end at zero speed.

But if there is a buffer full of short segments, what all together run only a few ms, that's not the case we worry about. We worry about the situation the buffer is full of long moves lasting together several seconds.

So if the break flag is set, simply ignore the deacceleration-point and always deaccelerate as much as possible (the info about how much is already in the buffer). If the segment ends just begin to run the next - immediately with the deaccelaration phase active. Until zero is reached. Then store the states.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/19253#issuecomment-691699993, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABE67NY4BRP3CB33Q4XCONTSFT6S3ANCNFSM4QVQTP5A.

AnHardt commented 4 years ago

Sorry. I'm currently not in the mood for holding the "beginners planner basics" course.

mron commented 4 years ago

No problem.

On Sep 13, 2020, at 3:33 PM, AnHardt notifications@github.com wrote:

 Sorry. I'm currently not in the mood for holding the "beginners planner basics" course.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

intuity-hans commented 3 years ago

@fedetony, are there any news on this subject?

fedetony commented 3 years ago

@intuity-hans I personally do not see an issue on my machine. When moving on the fastest speed and I use the pause it does not loose steps at all. I tried to modify the stepper function adding deceleration but it didn't work, and since I do not have a way of debugging it, I just left it there. The deceleration routines are implemented inside the stepper .C file I couldn't trigger them yet I only tried once. The fork is functional and updated, I can recheck it again if you specify exactly what you would like to have.. 👍

intuity-hans commented 3 years ago

Thanks for the quick reply! Just so I understand what you did – it is now possible to pause the program while it is executing a movement command. But, instead of an emergency stop (which clears the planner buffer) it is able to restart , right?

fedetony commented 3 years ago

it is now possible to pause the program while it is executing a movement command? Yes, the command P000 will pause Marlin while moving (probing,homing,or any positional movement). Will not do anything if not moving. For that you need M0 and M108 to resume

But, instead of an emergency stop (which clears the planner buffer) it is able to restart , right? Yes, When in P000 state, you can: Resume S000 and will continue where it was. stop (M410) (which clears the planner buffer) or kill M112 (you need to reset by HW after)

intuity-hans commented 3 years ago

okay thanks for clarifying. I will take a closer look at this. Seems fitting for my needs =)