|
@@ -498,20 +498,18 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
498
|
498
|
#if !UBL_SEGMENTED
|
499
|
499
|
#if IS_KINEMATIC
|
500
|
500
|
|
501
|
|
- #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
502
|
|
- #if ENABLED(DELTA)
|
503
|
|
- #define ADJUST_DELTA(V) \
|
504
|
|
- if (planner.leveling_active) { \
|
505
|
|
- const float zadj = bilinear_z_offset(V); \
|
506
|
|
- delta[A_AXIS] += zadj; \
|
507
|
|
- delta[B_AXIS] += zadj; \
|
508
|
|
- delta[C_AXIS] += zadj; \
|
509
|
|
- }
|
510
|
|
- #else
|
511
|
|
- #define ADJUST_DELTA(V) if (planner.leveling_active) { delta[Z_AXIS] += bilinear_z_offset(V); }
|
512
|
|
- #endif
|
513
|
|
- #else
|
514
|
|
- #define ADJUST_DELTA(V) NOOP
|
|
501
|
+ #if IS_SCARA
|
|
502
|
+ /**
|
|
503
|
+ * Before raising this value, use M665 S[seg_per_sec] to decrease
|
|
504
|
+ * the number of segments-per-second. Default is 200. Some deltas
|
|
505
|
+ * do better with 160 or lower. It would be good to know how many
|
|
506
|
+ * segments-per-second are actually possible for SCARA on AVR.
|
|
507
|
+ *
|
|
508
|
+ * Longer segments result in less kinematic overhead
|
|
509
|
+ * but may produce jagged lines. Try 0.5mm, 1.0mm, and 2.0mm
|
|
510
|
+ * and compare the difference.
|
|
511
|
+ */
|
|
512
|
+ #define SCARA_MIN_SEGMENT_LENGTH 0.5
|
515
|
513
|
#endif
|
516
|
514
|
|
517
|
515
|
/**
|
|
@@ -566,9 +564,9 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
566
|
564
|
// gives the number of segments
|
567
|
565
|
uint16_t segments = delta_segments_per_second * seconds;
|
568
|
566
|
|
569
|
|
- // For SCARA minimum segment size is 0.25mm
|
|
567
|
+ // For SCARA enforce a minimum segment size
|
570
|
568
|
#if IS_SCARA
|
571
|
|
- NOMORE(segments, cartesian_mm * 4);
|
|
569
|
+ NOMORE(segments, cartesian_mm * (1.0 / SCARA_MIN_SEGMENT_LENGTH));
|
572
|
570
|
#endif
|
573
|
571
|
|
574
|
572
|
// At least one segment is required
|
|
@@ -576,7 +574,6 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
576
|
574
|
|
577
|
575
|
// The approximate length of each segment
|
578
|
576
|
const float inv_segments = 1.0 / float(segments),
|
579
|
|
- cartesian_segment_mm = cartesian_mm * inv_segments,
|
580
|
577
|
segment_distance[XYZE] = {
|
581
|
578
|
xdiff * inv_segments,
|
582
|
579
|
ydiff * inv_segments,
|
|
@@ -584,16 +581,47 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
584
|
581
|
ediff * inv_segments
|
585
|
582
|
};
|
586
|
583
|
|
587
|
|
- // SERIAL_ECHOPAIR("mm=", cartesian_mm);
|
588
|
|
- // SERIAL_ECHOPAIR(" seconds=", seconds);
|
589
|
|
- // SERIAL_ECHOLNPAIR(" segments=", segments);
|
590
|
|
- // SERIAL_ECHOLNPAIR(" segment_mm=", cartesian_segment_mm);
|
|
584
|
+ #if DISABLED(SCARA_FEEDRATE_SCALING)
|
|
585
|
+ const float cartesian_segment_mm = cartesian_mm * inv_segments;
|
|
586
|
+ #endif
|
591
|
587
|
|
592
|
|
- // Get the current position as starting point
|
|
588
|
+ /*
|
|
589
|
+ SERIAL_ECHOPAIR("mm=", cartesian_mm);
|
|
590
|
+ SERIAL_ECHOPAIR(" seconds=", seconds);
|
|
591
|
+ SERIAL_ECHOPAIR(" segments=", segments);
|
|
592
|
+ #if DISABLED(SCARA_FEEDRATE_SCALING)
|
|
593
|
+ SERIAL_ECHOLNPAIR(" segment_mm=", cartesian_segment_mm);
|
|
594
|
+ #else
|
|
595
|
+ SERIAL_EOL();
|
|
596
|
+ #endif
|
|
597
|
+ //*/
|
|
598
|
+
|
|
599
|
+ #if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
600
|
+ // SCARA needs to scale the feed rate from mm/s to degrees/s
|
|
601
|
+ // i.e., Complete the angular vector in the given time.
|
|
602
|
+ const float segment_length = cartesian_mm * inv_segments,
|
|
603
|
+ inv_segment_length = 1.0 / segment_length, // 1/mm/segs
|
|
604
|
+ inverse_secs = inv_segment_length * _feedrate_mm_s;
|
|
605
|
+
|
|
606
|
+ float oldA = planner.position_float[A_AXIS],
|
|
607
|
+ oldB = planner.position_float[B_AXIS];
|
|
608
|
+
|
|
609
|
+ /*
|
|
610
|
+ SERIAL_ECHOPGM("Scaled kinematic move: ");
|
|
611
|
+ SERIAL_ECHOPAIR(" segment_length (inv)=", segment_length);
|
|
612
|
+ SERIAL_ECHOPAIR(" (", inv_segment_length);
|
|
613
|
+ SERIAL_ECHOPAIR(") _feedrate_mm_s=", _feedrate_mm_s);
|
|
614
|
+ SERIAL_ECHOPAIR(" inverse_secs=", inverse_secs);
|
|
615
|
+ SERIAL_ECHOPAIR(" oldA=", oldA);
|
|
616
|
+ SERIAL_ECHOLNPAIR(" oldB=", oldB);
|
|
617
|
+ safe_delay(5);
|
|
618
|
+ //*/
|
|
619
|
+ #endif
|
|
620
|
+
|
|
621
|
+ // Get the current position as starting point
|
593
|
622
|
float raw[XYZE];
|
594
|
623
|
COPY(raw, current_position);
|
595
|
624
|
|
596
|
|
-
|
597
|
625
|
// Calculate and execute the segments
|
598
|
626
|
while (--segments) {
|
599
|
627
|
|
|
@@ -613,11 +641,41 @@ float soft_endstop_min[XYZ] = { X_MIN_BED, Y_MIN_BED, Z_MIN_POS },
|
613
|
641
|
#endif
|
614
|
642
|
ADJUST_DELTA(raw); // Adjust Z if bed leveling is enabled
|
615
|
643
|
|
616
|
|
- planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder, cartesian_segment_mm);
|
|
644
|
+ #if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
645
|
+ // For SCARA scale the feed rate from mm/s to degrees/s
|
|
646
|
+ // i.e., Complete the angular vector in the given time.
|
|
647
|
+ planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], raw[Z_AXIS], raw[E_AXIS], HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs, active_extruder);
|
|
648
|
+ /*
|
|
649
|
+ SERIAL_ECHO(segments);
|
|
650
|
+ SERIAL_ECHOPAIR(": X=", raw[X_AXIS]); SERIAL_ECHOPAIR(" Y=", raw[Y_AXIS]);
|
|
651
|
+ SERIAL_ECHOPAIR(" A=", delta[A_AXIS]); SERIAL_ECHOPAIR(" B=", delta[B_AXIS]);
|
|
652
|
+ SERIAL_ECHOLNPAIR(" F", HYPOT(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB) * inverse_secs * 60);
|
|
653
|
+ safe_delay(5);
|
|
654
|
+ //*/
|
|
655
|
+ oldA = delta[A_AXIS]; oldB = delta[B_AXIS];
|
|
656
|
+ #else
|
|
657
|
+ planner.buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], raw[E_AXIS], _feedrate_mm_s, active_extruder, cartesian_segment_mm);
|
|
658
|
+ #endif
|
617
|
659
|
}
|
618
|
660
|
|
619
|
661
|
// Ensure last segment arrives at target location.
|
620
|
|
- planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder, cartesian_segment_mm);
|
|
662
|
+ #if ENABLED(SCARA_FEEDRATE_SCALING)
|
|
663
|
+ inverse_kinematics(rtarget);
|
|
664
|
+ ADJUST_DELTA(rtarget);
|
|
665
|
+ const float diff2 = HYPOT2(delta[A_AXIS] - oldA, delta[B_AXIS] - oldB);
|
|
666
|
+ if (diff2) {
|
|
667
|
+ planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], rtarget[Z_AXIS], rtarget[E_AXIS], SQRT(diff2) * inverse_secs, active_extruder);
|
|
668
|
+ /*
|
|
669
|
+ SERIAL_ECHOPAIR("final: A=", delta[A_AXIS]); SERIAL_ECHOPAIR(" B=", delta[B_AXIS]);
|
|
670
|
+ SERIAL_ECHOPAIR(" adiff=", delta[A_AXIS] - oldA); SERIAL_ECHOPAIR(" bdiff=", delta[B_AXIS] - oldB);
|
|
671
|
+ SERIAL_ECHOLNPAIR(" F", (SQRT(diff2) * inverse_secs) * 60);
|
|
672
|
+ SERIAL_EOL();
|
|
673
|
+ safe_delay(5);
|
|
674
|
+ //*/
|
|
675
|
+ }
|
|
676
|
+ #else
|
|
677
|
+ planner.buffer_line_kinematic(rtarget, _feedrate_mm_s, active_extruder, cartesian_segment_mm);
|
|
678
|
+ #endif
|
621
|
679
|
|
622
|
680
|
return false; // caller will update current_position
|
623
|
681
|
}
|