|
@@ -106,6 +106,17 @@ float destination[XYZE]; // = { 0 }
|
106
|
106
|
// Extruder offsets
|
107
|
107
|
#if HAS_HOTEND_OFFSET
|
108
|
108
|
float hotend_offset[XYZ][HOTENDS]; // Initialized by settings.load()
|
|
109
|
+ void reset_hotend_offsets() {
|
|
110
|
+ constexpr float tmp[XYZ][HOTENDS] = { HOTEND_OFFSET_X, HOTEND_OFFSET_Y, HOTEND_OFFSET_Z };
|
|
111
|
+ static_assert(
|
|
112
|
+ tmp[X_AXIS][0] == 0 && tmp[Y_AXIS][0] == 0 && tmp[Z_AXIS][0] == 0,
|
|
113
|
+ "Offsets for the first hotend must be 0.0."
|
|
114
|
+ );
|
|
115
|
+ LOOP_XYZ(i) HOTEND_LOOP() hotend_offset[i][e] = tmp[i][e];
|
|
116
|
+ #if ENABLED(DUAL_X_CARRIAGE)
|
|
117
|
+ hotend_offset[X_AXIS][1] = MAX(X2_HOME_POS, X2_MAX_POS);
|
|
118
|
+ #endif
|
|
119
|
+ }
|
109
|
120
|
#endif
|
110
|
121
|
|
111
|
122
|
// The feedrate for the current move, often used as the default if
|
|
@@ -130,11 +141,23 @@ const float homing_feedrate_mm_s[XYZ] PROGMEM = {
|
130
|
141
|
float cartes[XYZ];
|
131
|
142
|
|
132
|
143
|
#if IS_KINEMATIC
|
|
144
|
+
|
133
|
145
|
float delta[ABC];
|
134
|
|
-#endif
|
135
|
146
|
|
136
|
|
-#if HAS_SCARA_OFFSET
|
137
|
|
- float scara_home_offset[ABC];
|
|
147
|
+ #if HAS_SCARA_OFFSET
|
|
148
|
+ float scara_home_offset[ABC];
|
|
149
|
+ #endif
|
|
150
|
+
|
|
151
|
+ #if HAS_SOFTWARE_ENDSTOPS
|
|
152
|
+ float soft_endstop_radius, soft_endstop_radius_2;
|
|
153
|
+ #elif IS_SCARA
|
|
154
|
+ constexpr float soft_endstop_radius = SCARA_PRINTABLE_RADIUS,
|
|
155
|
+ soft_endstop_radius_2 = sq(SCARA_PRINTABLE_RADIUS);
|
|
156
|
+ #else // DELTA
|
|
157
|
+ constexpr float soft_endstop_radius = DELTA_PRINTABLE_RADIUS,
|
|
158
|
+ soft_endstop_radius_2 = sq(DELTA_PRINTABLE_RADIUS);
|
|
159
|
+ #endif
|
|
160
|
+
|
138
|
161
|
#endif
|
139
|
162
|
|
140
|
163
|
/**
|
|
@@ -440,47 +463,6 @@ void clean_up_after_endstop_or_probe_move() {
|
440
|
463
|
float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
441
|
464
|
soft_endstop_max[XYZ] = { X_MAX_BED, Y_MAX_BED, Z_MAX_POS };
|
442
|
465
|
|
443
|
|
- #if IS_KINEMATIC
|
444
|
|
- float soft_endstop_radius, soft_endstop_radius_2;
|
445
|
|
- #endif
|
446
|
|
-
|
447
|
|
- /**
|
448
|
|
- * Constrain the given coordinates to the software endstops.
|
449
|
|
- *
|
450
|
|
- * For DELTA/SCARA the XY constraint is based on the smallest
|
451
|
|
- * radius within the set software endstops.
|
452
|
|
- */
|
453
|
|
- void clamp_to_software_endstops(float target[XYZ]) {
|
454
|
|
- if (!soft_endstops_enabled) return;
|
455
|
|
- #if IS_KINEMATIC
|
456
|
|
- const float dist_2 = HYPOT2(target[X_AXIS], target[Y_AXIS]);
|
457
|
|
- if (dist_2 > soft_endstop_radius_2) {
|
458
|
|
- const float ratio = soft_endstop_radius / SQRT(dist_2); // 200 / 300 = 0.66
|
459
|
|
- target[X_AXIS] *= ratio;
|
460
|
|
- target[Y_AXIS] *= ratio;
|
461
|
|
- }
|
462
|
|
- #else
|
463
|
|
- #if ENABLED(MIN_SOFTWARE_ENDSTOP_X)
|
464
|
|
- NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]);
|
465
|
|
- #endif
|
466
|
|
- #if ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
|
467
|
|
- NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]);
|
468
|
|
- #endif
|
469
|
|
- #if ENABLED(MAX_SOFTWARE_ENDSTOP_X)
|
470
|
|
- NOMORE(target[X_AXIS], soft_endstop_max[X_AXIS]);
|
471
|
|
- #endif
|
472
|
|
- #if ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
|
473
|
|
- NOMORE(target[Y_AXIS], soft_endstop_max[Y_AXIS]);
|
474
|
|
- #endif
|
475
|
|
- #endif
|
476
|
|
- #if ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
|
477
|
|
- NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]);
|
478
|
|
- #endif
|
479
|
|
- #if ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
|
480
|
|
- NOMORE(target[Z_AXIS], soft_endstop_max[Z_AXIS]);
|
481
|
|
- #endif
|
482
|
|
- }
|
483
|
|
-
|
484
|
466
|
/**
|
485
|
467
|
* Software endstops can be used to monitor the open end of
|
486
|
468
|
* an axis that has a hardware endstop on the other end. Or
|
|
@@ -490,7 +472,11 @@ void clean_up_after_endstop_or_probe_move() {
|
490
|
472
|
* the software endstop positions must be refreshed to remain
|
491
|
473
|
* at the same positions relative to the machine.
|
492
|
474
|
*/
|
493
|
|
- void update_software_endstops(const AxisEnum axis) {
|
|
475
|
+ void update_software_endstops(const AxisEnum axis
|
|
476
|
+ #if HAS_HOTEND_OFFSET
|
|
477
|
+ , const uint8_t old_tool_index/*=0*/, const uint8_t new_tool_index/*=0*/
|
|
478
|
+ #endif
|
|
479
|
+ ) {
|
494
|
480
|
|
495
|
481
|
#if ENABLED(DUAL_X_CARRIAGE)
|
496
|
482
|
|
|
@@ -499,7 +485,7 @@ void clean_up_after_endstop_or_probe_move() {
|
499
|
485
|
// In Dual X mode hotend_offset[X] is T1's home position
|
500
|
486
|
const float dual_max_x = MAX(hotend_offset[X_AXIS][1], X2_MAX_POS);
|
501
|
487
|
|
502
|
|
- if (active_extruder != 0) {
|
|
488
|
+ if (new_tool_index != 0) {
|
503
|
489
|
// T1 can move from X2_MIN_POS to X2_MAX_POS or X2 home position (whichever is larger)
|
504
|
490
|
soft_endstop_min[X_AXIS] = X2_MIN_POS;
|
505
|
491
|
soft_endstop_max[X_AXIS] = dual_max_x;
|
|
@@ -538,6 +524,22 @@ void clean_up_after_endstop_or_probe_move() {
|
538
|
524
|
default: break;
|
539
|
525
|
}
|
540
|
526
|
|
|
527
|
+ #elif HAS_HOTEND_OFFSET
|
|
528
|
+
|
|
529
|
+ // Software endstops are relative to the tool 0 workspace, so
|
|
530
|
+ // the movement limits must be shifted by the tool offset to
|
|
531
|
+ // retain the same physical limit when other tools are selected.
|
|
532
|
+ if (old_tool_index != new_tool_index) {
|
|
533
|
+ const float offs = hotend_offset[axis][new_tool_index] - hotend_offset[axis][old_tool_index];
|
|
534
|
+ soft_endstop_min[axis] += offs;
|
|
535
|
+ soft_endstop_max[axis] += offs;
|
|
536
|
+ }
|
|
537
|
+ else {
|
|
538
|
+ const float offs = hotend_offset[axis][active_extruder];
|
|
539
|
+ soft_endstop_min[axis] = base_min_pos(axis) + offs;
|
|
540
|
+ soft_endstop_max[axis] = base_max_pos(axis) + offs;
|
|
541
|
+ }
|
|
542
|
+
|
541
|
543
|
#else
|
542
|
544
|
|
543
|
545
|
soft_endstop_min[axis] = base_min_pos(axis);
|
|
@@ -554,7 +556,59 @@ void clean_up_after_endstop_or_probe_move() {
|
554
|
556
|
#endif
|
555
|
557
|
}
|
556
|
558
|
|
557
|
|
-#endif
|
|
559
|
+#endif // HAS_SOFTWARE_ENDSTOPS
|
|
560
|
+
|
|
561
|
+/**
|
|
562
|
+ * Constrain the given coordinates to the software endstops.
|
|
563
|
+ *
|
|
564
|
+ * For DELTA/SCARA the XY constraint is based on the smallest
|
|
565
|
+ * radius within the set software endstops.
|
|
566
|
+ */
|
|
567
|
+void clamp_to_software_endstops(float target[XYZ]) {
|
|
568
|
+
|
|
569
|
+ if (!soft_endstops_enabled) return;
|
|
570
|
+
|
|
571
|
+ #if IS_KINEMATIC
|
|
572
|
+
|
|
573
|
+ #if HAS_HOTEND_OFFSET && ENABLED(DELTA)
|
|
574
|
+ // The effector center position will be the target minus the hotend offset.
|
|
575
|
+ const float offx = hotend_offset[X_AXIS][active_extruder], offy = hotend_offset[Y_AXIS][active_extruder];
|
|
576
|
+ #else
|
|
577
|
+ // SCARA needs to consider the angle of the arm through the entire move, so for now use no tool offset.
|
|
578
|
+ constexpr float offx = 0, offy = 0;
|
|
579
|
+ #endif
|
|
580
|
+
|
|
581
|
+ const float dist_2 = HYPOT2(target[X_AXIS] - offx, target[Y_AXIS] - offy);
|
|
582
|
+ if (dist_2 > soft_endstop_radius_2) {
|
|
583
|
+ const float ratio = (soft_endstop_radius) / SQRT(dist_2); // 200 / 300 = 0.66
|
|
584
|
+ target[X_AXIS] *= ratio;
|
|
585
|
+ target[Y_AXIS] *= ratio;
|
|
586
|
+ }
|
|
587
|
+
|
|
588
|
+ #else
|
|
589
|
+
|
|
590
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_X)
|
|
591
|
+ NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]);
|
|
592
|
+ #endif
|
|
593
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_X)
|
|
594
|
+ NOMORE(target[X_AXIS], soft_endstop_max[X_AXIS]);
|
|
595
|
+ #endif
|
|
596
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
|
|
597
|
+ NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]);
|
|
598
|
+ #endif
|
|
599
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
|
|
600
|
+ NOMORE(target[Y_AXIS], soft_endstop_max[Y_AXIS]);
|
|
601
|
+ #endif
|
|
602
|
+
|
|
603
|
+ #endif
|
|
604
|
+
|
|
605
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
|
|
606
|
+ NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]);
|
|
607
|
+ #endif
|
|
608
|
+ #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
|
|
609
|
+ NOMORE(target[Z_AXIS], soft_endstop_max[Z_AXIS]);
|
|
610
|
+ #endif
|
|
611
|
+}
|
558
|
612
|
|
559
|
613
|
#if !UBL_SEGMENTED
|
560
|
614
|
#if IS_KINEMATIC
|