瀏覽代碼

Fix Bresenham rounding errors, add link to article (#10871)

Eduardo José Tagle 6 年之前
父節點
當前提交
7b9f0302d4
共有 1 個文件被更改,包括 17 次插入10 次删除
  1. 17
    10
      Marlin/src/module/stepper.cpp

+ 17
- 10
Marlin/src/module/stepper.cpp 查看文件

@@ -111,6 +111,13 @@ bool Stepper::abort_current_block;
111 111
   bool Stepper::locked_z_motor = false, Stepper::locked_z2_motor = false;
112 112
 #endif
113 113
 
114
+/**
115
+ * Marlin uses the Bresenham algorithm. For a detailed explanation of theory and
116
+ * method see https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
117
+ *
118
+ * The implementation used here additionally rounds up the starting seed.
119
+ */
120
+
114 121
 int32_t Stepper::counter_X = 0,
115 122
         Stepper::counter_Y = 0,
116 123
         Stepper::counter_Z = 0,
@@ -1174,7 +1181,7 @@ hal_timer_t Stepper::isr_scheduler() {
1174 1181
 
1175 1182
   // Limit the amount of iterations
1176 1183
   uint8_t max_loops = 10;
1177
-  
1184
+
1178 1185
   // We need this variable here to be able to use it in the following loop
1179 1186
   hal_timer_t min_ticks;
1180 1187
   do {
@@ -1294,12 +1301,12 @@ void Stepper::stepper_pulse_phase_isr() {
1294 1301
     // Advance the Bresenham counter; start a pulse if the axis needs a step
1295 1302
     #define PULSE_START(AXIS) do{ \
1296 1303
       _COUNTER(AXIS) += current_block->steps[_AXIS(AXIS)]; \
1297
-      if (_COUNTER(AXIS) > 0) { _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), 0); } \
1304
+      if (_COUNTER(AXIS) >= 0) { _APPLY_STEP(AXIS)(!_INVERT_STEP_PIN(AXIS), 0); } \
1298 1305
     }while(0)
1299 1306
 
1300 1307
     // Advance the Bresenham counter; start a pulse if the axis needs a step
1301 1308
     #define STEP_TICK(AXIS) do { \
1302
-      if (_COUNTER(AXIS) > 0) { \
1309
+      if (_COUNTER(AXIS) >= 0) { \
1303 1310
         _COUNTER(AXIS) -= current_block->step_event_count; \
1304 1311
         count_position[_AXIS(AXIS)] += count_direction[_AXIS(AXIS)]; \
1305 1312
       } \
@@ -1387,7 +1394,7 @@ void Stepper::stepper_pulse_phase_isr() {
1387 1394
 
1388 1395
     #if ENABLED(LIN_ADVANCE)
1389 1396
       counter_E += current_block->steps[E_AXIS];
1390
-      if (counter_E > 0) {
1397
+      if (counter_E >= 0) {
1391 1398
         #if DISABLED(MIXING_EXTRUDER)
1392 1399
           // Don't step E here for mixing extruder
1393 1400
           motor_direction(E_AXIS) ? --e_steps : ++e_steps;
@@ -1399,7 +1406,7 @@ void Stepper::stepper_pulse_phase_isr() {
1399 1406
         const bool dir = motor_direction(E_AXIS);
1400 1407
         MIXING_STEPPERS_LOOP(j) {
1401 1408
           counter_m[j] += current_block->steps[E_AXIS];
1402
-          if (counter_m[j] > 0) {
1409
+          if (counter_m[j] >= 0) {
1403 1410
             counter_m[j] -= current_block->mix_event_count[j];
1404 1411
             dir ? --e_steps[j] : ++e_steps[j];
1405 1412
           }
@@ -1416,7 +1423,7 @@ void Stepper::stepper_pulse_phase_isr() {
1416 1423
           // Step mixing steppers (proportionally)
1417 1424
           counter_m[j] += current_block->steps[E_AXIS];
1418 1425
           // Step when the counter goes over zero
1419
-          if (counter_m[j] > 0) En_STEP_WRITE(j, !INVERT_E_STEP_PIN);
1426
+          if (counter_m[j] >= 0) En_STEP_WRITE(j, !INVERT_E_STEP_PIN);
1420 1427
         }
1421 1428
       #else // !MIXING_EXTRUDER
1422 1429
         PULSE_START(E);
@@ -1456,7 +1463,7 @@ void Stepper::stepper_pulse_phase_isr() {
1456 1463
     #if DISABLED(LIN_ADVANCE)
1457 1464
       #if ENABLED(MIXING_EXTRUDER)
1458 1465
         MIXING_STEPPERS_LOOP(j) {
1459
-          if (counter_m[j] > 0) {
1466
+          if (counter_m[j] >= 0) {
1460 1467
             counter_m[j] -= current_block->mix_event_count[j];
1461 1468
             En_STEP_WRITE(j, INVERT_E_STEP_PIN);
1462 1469
           }
@@ -1738,11 +1745,11 @@ uint32_t Stepper::stepper_block_phase_isr() {
1738 1745
         bezier_2nd_half = false;
1739 1746
       #endif
1740 1747
 
1741
-      // Initialize Bresenham counters to 1/2 the ceiling
1742
-      counter_X = counter_Y = counter_Z = counter_E = -((int32_t)(current_block->step_event_count >> 1));
1748
+      // Initialize Bresenham counters to 1/2 the ceiling, with proper roundup (as explained in the article linked above)
1749
+      counter_X = counter_Y = counter_Z = counter_E = -int32_t((current_block->step_event_count + 1) >> 1);
1743 1750
       #if ENABLED(MIXING_EXTRUDER)
1744 1751
         MIXING_STEPPERS_LOOP(i)
1745
-          counter_m[i] = -(current_block->mix_event_count[i] >> 1);
1752
+          counter_m[i] = -int32_t((current_block->mix_event_count[i] + 1) >> 1);
1746 1753
       #endif
1747 1754
 
1748 1755
       #if ENABLED(Z_LATE_ENABLE)

Loading…
取消
儲存