Преглед изворни кода

Fix overflow and infloop with LA15 and low step rates

When calculating the advance tick interval, be sure to check for integer
overflow. Very low step rates can result in values exceeding uint16_t
causing premature LA tick delivery.

An overflow resulting in zero would also block in an infinite loop
within advance_spread().

Even though such rates are worthless in terms of compensation and often
result in 0 extra ticks as well, do not disable LA for the block (as
doing so would reset the count for short segments) and do not check for
zero in multiple paces either.

Saturate the interval instead, delaying any further tick to the next
block.
Yuri D'Elia пре 4 година
родитељ
комит
47db75d5fd
1 измењених фајлова са 12 додато и 5 уклоњено
  1. 12 5
      Firmware/planner.cpp

+ 12 - 5
Firmware/planner.cpp

@@ -1137,17 +1137,24 @@ Having the real displacement of the head, we can calculate the total movement le
       // still need to replicate the *exact* same step grouping policy (see below)
       float advance_speed = (extruder_advance_K * e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
       if (advance_speed > MAX_STEP_FREQUENCY) advance_speed = MAX_STEP_FREQUENCY;
-      block->advance_rate = (F_CPU / 8.0) / advance_speed;
-      if (block->advance_rate > 20000) {
-          block->advance_rate = (block->advance_rate >> 2)&0x3fff;
+      float advance_rate = (F_CPU / 8.0) / advance_speed;
+      if (advance_speed > 20000) {
+          block->advance_rate = advance_rate * 4;
           block->advance_step_loops = 4;
       }
-      else if (block->advance_rate > 10000) {
-          block->advance_rate = (block->advance_rate >> 1)&0x7fff;
+      else if (advance_speed > 10000) {
+          block->advance_rate = advance_rate * 2;
           block->advance_step_loops = 2;
       }
       else
+      {
+          // never overflow the internal accumulator with very low rates
+          if (advance_rate < UINT16_MAX)
+              block->advance_rate = advance_rate;
+          else
+              block->advance_rate = UINT16_MAX;
           block->advance_step_loops = 1;
+      }
 
       #ifdef LA_DEBUG
       if (block->advance_step_loops > 2)