|
@@ -286,23 +286,73 @@ bool Running = true;
|
286
|
286
|
|
287
|
287
|
uint8_t marlin_debug_flags = DEBUG_NONE;
|
288
|
288
|
|
289
|
|
-float current_position[NUM_AXIS] = { 0.0 };
|
290
|
|
-static float destination[NUM_AXIS] = { 0.0 };
|
291
|
|
-bool axis_known_position[XYZ] = { false };
|
292
|
|
-bool axis_homed[XYZ] = { false };
|
|
289
|
+/**
|
|
290
|
+ * Cartesian Current Position
|
|
291
|
+ * Used to track the logical position as moves are queued.
|
|
292
|
+ * Used by 'line_to_current_position' to do a move after changing it.
|
|
293
|
+ * Used by 'SYNC_PLAN_POSITION_KINEMATIC' to update 'planner.position'.
|
|
294
|
+ */
|
|
295
|
+float current_position[XYZE] = { 0.0 };
|
|
296
|
+
|
|
297
|
+/**
|
|
298
|
+ * Cartesian Destination
|
|
299
|
+ * A temporary position, usually applied to 'current_position'.
|
|
300
|
+ * Set with 'gcode_get_destination' or 'set_destination_to_current'.
|
|
301
|
+ * 'line_to_destination' sets 'current_position' to 'destination'.
|
|
302
|
+ */
|
|
303
|
+static float destination[XYZE] = { 0.0 };
|
|
304
|
+
|
|
305
|
+/**
|
|
306
|
+ * axis_homed
|
|
307
|
+ * Flags that each linear axis was homed.
|
|
308
|
+ * XYZ on cartesian, ABC on delta, ABZ on SCARA.
|
|
309
|
+ *
|
|
310
|
+ * axis_known_position
|
|
311
|
+ * Flags that the position is known in each linear axis. Set when homed.
|
|
312
|
+ * Cleared whenever a stepper powers off, potentially losing its position.
|
|
313
|
+ */
|
|
314
|
+bool axis_homed[XYZ] = { false }, axis_known_position[XYZ] = { false };
|
293
|
315
|
|
|
316
|
+/**
|
|
317
|
+ * GCode line number handling. Hosts may opt to include line numbers when
|
|
318
|
+ * sending commands to Marlin, and lines will be checked for sequentiality.
|
|
319
|
+ * M110 S<int> sets the current line number.
|
|
320
|
+ */
|
294
|
321
|
static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
|
295
|
322
|
|
|
323
|
+/**
|
|
324
|
+ * GCode Command Queue
|
|
325
|
+ * A simple ring buffer of BUFSIZE command strings.
|
|
326
|
+ *
|
|
327
|
+ * Commands are copied into this buffer by the command injectors
|
|
328
|
+ * (immediate, serial, sd card) and they are processed sequentially by
|
|
329
|
+ * the main loop. The process_next_command function parses the next
|
|
330
|
+ * command and hands off execution to individual handler functions.
|
|
331
|
+ */
|
296
|
332
|
static char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
297
|
|
-static char* current_command, *current_command_args;
|
298
|
|
-static uint8_t cmd_queue_index_r = 0,
|
299
|
|
- cmd_queue_index_w = 0,
|
300
|
|
- commands_in_queue = 0;
|
|
333
|
+static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
|
|
334
|
+ cmd_queue_index_w = 0, // Ring buffer write position
|
|
335
|
+ commands_in_queue = 0; // Count of commands in the queue
|
|
336
|
+
|
|
337
|
+/**
|
|
338
|
+ * Current GCode Command
|
|
339
|
+ * When a GCode handler is running, these will be set
|
|
340
|
+ */
|
|
341
|
+static char *current_command, // The command currently being executed
|
|
342
|
+ *current_command_args, // The address where arguments begin
|
|
343
|
+ *seen_pointer; // Set by code_seen(), used by the code_value functions
|
|
344
|
+
|
|
345
|
+/**
|
|
346
|
+ * Next Injected Command pointer. NULL if no commands are being injected.
|
|
347
|
+ * Used by Marlin internally to ensure that commands initiated from within
|
|
348
|
+ * are enqueued ahead of any pending serial or sd card commands.
|
|
349
|
+ */
|
|
350
|
+static const char *injected_commands_P = NULL;
|
301
|
351
|
|
302
|
352
|
#if ENABLED(INCH_MODE_SUPPORT)
|
303
|
|
- float linear_unit_factor = 1.0;
|
304
|
|
- float volumetric_unit_factor = 1.0;
|
|
353
|
+ float linear_unit_factor = 1.0, volumetric_unit_factor = 1.0;
|
305
|
354
|
#endif
|
|
355
|
+
|
306
|
356
|
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
|
307
|
357
|
TempUnit input_temp_units = TEMPUNIT_C;
|
308
|
358
|
#endif
|
|
@@ -320,13 +370,13 @@ float constexpr homing_feedrate_mm_s[] = {
|
320
|
370
|
MMM_TO_MMS(HOMING_FEEDRATE_Z), 0
|
321
|
371
|
};
|
322
|
372
|
static float feedrate_mm_s = MMM_TO_MMS(1500.0), saved_feedrate_mm_s;
|
323
|
|
-int feedrate_percentage = 100, saved_feedrate_percentage;
|
|
373
|
+int feedrate_percentage = 100, saved_feedrate_percentage,
|
|
374
|
+ flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
|
324
|
375
|
|
325
|
|
-bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
|
326
|
|
-int flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100);
|
327
|
|
-bool volumetric_enabled = false;
|
328
|
|
-float filament_size[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_NOMINAL_FILAMENT_DIA);
|
329
|
|
-float volumetric_multiplier[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0);
|
|
376
|
+bool axis_relative_modes[] = AXIS_RELATIVE_MODES,
|
|
377
|
+ volumetric_enabled = false;
|
|
378
|
+float filament_size[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(DEFAULT_NOMINAL_FILAMENT_DIA),
|
|
379
|
+ volumetric_multiplier[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(1.0);
|
330
|
380
|
|
331
|
381
|
// The distance that XYZ has been offset by G92. Reset by G28.
|
332
|
382
|
float position_shift[XYZ] = { 0 };
|
|
@@ -364,12 +414,6 @@ const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
|
364
|
414
|
|
365
|
415
|
static int serial_count = 0;
|
366
|
416
|
|
367
|
|
-// GCode parameter pointer used by code_seen(), code_value_float(), etc.
|
368
|
|
-static char* seen_pointer;
|
369
|
|
-
|
370
|
|
-// Next Immediate GCode Command pointer. NULL if none.
|
371
|
|
-const char* queued_commands_P = NULL;
|
372
|
|
-
|
373
|
417
|
const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
|
374
|
418
|
|
375
|
419
|
// Inactivity shutdown
|
|
@@ -706,32 +750,32 @@ extern "C" {
|
706
|
750
|
* Inject the next "immediate" command, when possible.
|
707
|
751
|
* Return true if any immediate commands remain to inject.
|
708
|
752
|
*/
|
709
|
|
-static bool drain_queued_commands_P() {
|
710
|
|
- if (queued_commands_P != NULL) {
|
|
753
|
+static bool drain_injected_commands_P() {
|
|
754
|
+ if (injected_commands_P != NULL) {
|
711
|
755
|
size_t i = 0;
|
712
|
756
|
char c, cmd[30];
|
713
|
|
- strncpy_P(cmd, queued_commands_P, sizeof(cmd) - 1);
|
|
757
|
+ strncpy_P(cmd, injected_commands_P, sizeof(cmd) - 1);
|
714
|
758
|
cmd[sizeof(cmd) - 1] = '\0';
|
715
|
759
|
while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
|
716
|
760
|
cmd[i] = '\0';
|
717
|
761
|
if (enqueue_and_echo_command(cmd)) { // success?
|
718
|
762
|
if (c) // newline char?
|
719
|
|
- queued_commands_P += i + 1; // advance to the next command
|
|
763
|
+ injected_commands_P += i + 1; // advance to the next command
|
720
|
764
|
else
|
721
|
|
- queued_commands_P = NULL; // nul char? no more commands
|
|
765
|
+ injected_commands_P = NULL; // nul char? no more commands
|
722
|
766
|
}
|
723
|
767
|
}
|
724
|
|
- return (queued_commands_P != NULL); // return whether any more remain
|
|
768
|
+ return (injected_commands_P != NULL); // return whether any more remain
|
725
|
769
|
}
|
726
|
770
|
|
727
|
771
|
/**
|
728
|
772
|
* Record one or many commands to run from program memory.
|
729
|
773
|
* Aborts the current queue, if any.
|
730
|
|
- * Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards
|
|
774
|
+ * Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
|
731
|
775
|
*/
|
732
|
776
|
void enqueue_and_echo_commands_P(const char* pgcode) {
|
733
|
|
- queued_commands_P = pgcode;
|
734
|
|
- drain_queued_commands_P(); // first command executed asap (when possible)
|
|
777
|
+ injected_commands_P = pgcode;
|
|
778
|
+ drain_injected_commands_P(); // first command executed asap (when possible)
|
735
|
779
|
}
|
736
|
780
|
|
737
|
781
|
void clear_command_queue() {
|
|
@@ -1085,14 +1129,14 @@ inline void get_serial_commands() {
|
1085
|
1129
|
|
1086
|
1130
|
/**
|
1087
|
1131
|
* Add to the circular command queue the next command from:
|
1088
|
|
- * - The command-injection queue (queued_commands_P)
|
|
1132
|
+ * - The command-injection queue (injected_commands_P)
|
1089
|
1133
|
* - The active serial input (usually USB)
|
1090
|
1134
|
* - The SD card file being actively printed
|
1091
|
1135
|
*/
|
1092
|
1136
|
void get_available_commands() {
|
1093
|
1137
|
|
1094
|
1138
|
// if any immediate commands remain, don't get other commands yet
|
1095
|
|
- if (drain_queued_commands_P()) return;
|
|
1139
|
+ if (drain_injected_commands_P()) return;
|
1096
|
1140
|
|
1097
|
1141
|
get_serial_commands();
|
1098
|
1142
|
|
|
@@ -8862,15 +8906,11 @@ void prepare_move_to_destination() {
|
8862
|
8906
|
uint16_t segments = floor(mm_of_travel / (MM_PER_ARC_SEGMENT));
|
8863
|
8907
|
if (segments == 0) segments = 1;
|
8864
|
8908
|
|
8865
|
|
- float theta_per_segment = angular_travel / segments;
|
8866
|
|
- float linear_per_segment = linear_travel / segments;
|
8867
|
|
- float extruder_per_segment = extruder_travel / segments;
|
8868
|
|
-
|
8869
|
8909
|
/**
|
8870
|
8910
|
* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
8871
|
8911
|
* and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
|
8872
|
8912
|
* r_T = [cos(phi) -sin(phi);
|
8873
|
|
- * sin(phi) cos(phi] * r ;
|
|
8913
|
+ * sin(phi) cos(phi)] * r ;
|
8874
|
8914
|
*
|
8875
|
8915
|
* For arc generation, the center of the circle is the axis of rotation and the radius vector is
|
8876
|
8916
|
* defined from the circle center to the initial position. Each line segment is formed by successive
|
|
@@ -8893,13 +8933,12 @@ void prepare_move_to_destination() {
|
8893
|
8933
|
* This is important when there are successive arc motions.
|
8894
|
8934
|
*/
|
8895
|
8935
|
// Vector rotation matrix values
|
8896
|
|
- float cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
|
8897
|
|
- float sin_T = theta_per_segment;
|
8898
|
|
-
|
8899
|
|
- float arc_target[NUM_AXIS];
|
8900
|
|
- float sin_Ti, cos_Ti, r_new_Y;
|
8901
|
|
- uint16_t i;
|
8902
|
|
- int8_t count = 0;
|
|
8936
|
+ float arc_target[XYZE],
|
|
8937
|
+ theta_per_segment = angular_travel / segments,
|
|
8938
|
+ linear_per_segment = linear_travel / segments,
|
|
8939
|
+ extruder_per_segment = extruder_travel / segments,
|
|
8940
|
+ sin_T = theta_per_segment,
|
|
8941
|
+ cos_T = 1 - 0.5 * sq(theta_per_segment); // Small angle approximation
|
8903
|
8942
|
|
8904
|
8943
|
// Initialize the linear axis
|
8905
|
8944
|
arc_target[Z_AXIS] = current_position[Z_AXIS];
|
|
@@ -8911,18 +8950,18 @@ void prepare_move_to_destination() {
|
8911
|
8950
|
|
8912
|
8951
|
millis_t next_idle_ms = millis() + 200UL;
|
8913
|
8952
|
|
8914
|
|
- for (i = 1; i < segments; i++) { // Iterate (segments-1) times
|
|
8953
|
+ int8_t count = 0;
|
|
8954
|
+ for (uint16_t i = 1; i < segments; i++) { // Iterate (segments-1) times
|
8915
|
8955
|
|
8916
|
8956
|
thermalManager.manage_heater();
|
8917
|
|
- millis_t now = millis();
|
8918
|
|
- if (ELAPSED(now, next_idle_ms)) {
|
8919
|
|
- next_idle_ms = now + 200UL;
|
|
8957
|
+ if (ELAPSED(millis(), next_idle_ms)) {
|
|
8958
|
+ next_idle_ms = millis() + 200UL;
|
8920
|
8959
|
idle();
|
8921
|
8960
|
}
|
8922
|
8961
|
|
8923
|
8962
|
if (++count < N_ARC_CORRECTION) {
|
8924
|
8963
|
// Apply vector rotation matrix to previous r_X / 1
|
8925
|
|
- r_new_Y = r_X * sin_T + r_Y * cos_T;
|
|
8964
|
+ float r_new_Y = r_X * sin_T + r_Y * cos_T;
|
8926
|
8965
|
r_X = r_X * cos_T - r_Y * sin_T;
|
8927
|
8966
|
r_Y = r_new_Y;
|
8928
|
8967
|
}
|
|
@@ -8931,8 +8970,8 @@ void prepare_move_to_destination() {
|
8931
|
8970
|
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
8932
|
8971
|
// To reduce stuttering, the sin and cos could be computed at different times.
|
8933
|
8972
|
// For now, compute both at the same time.
|
8934
|
|
- cos_Ti = cos(i * theta_per_segment);
|
8935
|
|
- sin_Ti = sin(i * theta_per_segment);
|
|
8973
|
+ float cos_Ti = cos(i * theta_per_segment),
|
|
8974
|
+ sin_Ti = sin(i * theta_per_segment);
|
8936
|
8975
|
r_X = -offset[X_AXIS] * cos_Ti + offset[Y_AXIS] * sin_Ti;
|
8937
|
8976
|
r_Y = -offset[X_AXIS] * sin_Ti - offset[Y_AXIS] * cos_Ti;
|
8938
|
8977
|
count = 0;
|
|
@@ -9202,8 +9241,7 @@ void prepare_move_to_destination() {
|
9202
|
9241
|
|
9203
|
9242
|
float calculate_volumetric_multiplier(float diameter) {
|
9204
|
9243
|
if (!volumetric_enabled || diameter == 0) return 1.0;
|
9205
|
|
- float d2 = diameter * 0.5;
|
9206
|
|
- return 1.0 / (M_PI * d2 * d2);
|
|
9244
|
+ return 1.0 / (M_PI * diameter * 0.5 * diameter * 0.5);
|
9207
|
9245
|
}
|
9208
|
9246
|
|
9209
|
9247
|
void calculate_volumetric_multipliers() {
|