Ver Fonte

Update/compute advance steps inside calculate_trapezoid_for_block

Do not store the block e_D ratio, store directly the computed
compression factor so that we can recompute the advance steps
quickly and update them in sync with the acceleration rates.
Yuri D'Elia há 5 anos atrás
pai
commit
0239f4bce1
3 ficheiros alterados com 33 adições e 31 exclusões
  1. 30 29
      Firmware/planner.cpp
  2. 1 1
      Firmware/planner.h
  3. 2 1
      Firmware/stepper.cpp

+ 30 - 29
Firmware/planner.cpp

@@ -261,6 +261,13 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
     }
   }
 
+#ifdef LIN_ADVANCE
+  uint16_t final_adv_steps = 0;
+  if (block->use_advance_lead) {
+      final_adv_steps = exit_speed * block->adv_comp;
+  }
+#endif
+
   CRITICAL_SECTION_START;  // Fill variables used by the stepper in a critical section
   // This block locks the interrupts globally for 4.38 us,
   // which corresponds to a maximum repeat frequency of 228.57 kHz.
@@ -271,6 +278,9 @@ void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit
     block->decelerate_after = accelerate_steps+plateau_steps;
     block->initial_rate = initial_rate;
     block->final_rate = final_rate;
+#ifdef LIN_ADVANCE
+    block->final_adv_steps = final_adv_steps;
+#endif
   }
   CRITICAL_SECTION_END;
 }
@@ -399,18 +409,8 @@ void planner_recalculate(const float &safe_final_speed)
             }
             // Recalculate if current block entry or exit junction speed has changed.
             if ((prev->flag | current->flag) & BLOCK_FLAG_RECALCULATE) {
-                // @wavexx: FIXME: the following check is not really enough. calculate_trapezoid does block
-                //          the isr to update the rates, but we don't. we should update atomically
-                if (!prev->busy) {
-                    // NOTE: Entry and exit factors always > 0 by all previous logic operations.
-                    calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed);
-                    #ifdef LIN_ADVANCE
-                    if (prev->use_advance_lead) {
-                        const float comp = prev->e_D_ratio * extruder_advance_K * cs.axis_steps_per_unit[E_AXIS];
-                        prev->final_adv_steps = current->entry_speed * comp;
-                    }
-                    #endif
-                }
+                // NOTE: Entry and exit factors always > 0 by all previous logic operations.
+                calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed);
                 // Reset current only to ensure next trapezoid is computed.
                 prev->flag &= ~BLOCK_FLAG_RECALCULATE;
             }
@@ -424,13 +424,6 @@ void planner_recalculate(const float &safe_final_speed)
     // Last/newest block in buffer. Exit speed is set with safe_final_speed. Always recalculated.
     current = block_buffer + prev_block_index(block_buffer_head);
     calculate_trapezoid_for_block(current, current->entry_speed, safe_final_speed);
-    #ifdef LIN_ADVANCE
-    if (current->use_advance_lead) {
-      const float comp = current->e_D_ratio * extruder_advance_K * cs.axis_steps_per_unit[E_AXIS];
-      current->max_adv_steps = current->nominal_speed * comp;
-      current->final_adv_steps = safe_final_speed * comp;
-    }
-    #endif
     current->flag &= ~BLOCK_FLAG_RECALCULATE;
 
 //    SERIAL_ECHOLNPGM("planner_recalculate - 4");
@@ -1005,6 +998,9 @@ Having the real displacement of the head, we can calculate the total movement le
     block->nominal_rate *= speed_factor;
   }
 
+#ifdef LIN_ADVANCE
+  float e_D_ratio = 0;
+#endif
   // Compute and limit the acceleration rate for the trapezoid generator.  
   // block->step_event_count ... event count of the fastest axis
   // block->millimeters ... Euclidian length of the XYZ movement or the E length, if no XYZ movement.
@@ -1022,7 +1018,7 @@ Having the real displacement of the head, we can calculate the total movement le
 
     #ifdef LIN_ADVANCE
     /**
-     * Use LIN_ADVANCE for blocks if all these are true:
+     * Use LIN_ADVANCE within this block if all these are true:
      *
      * block->steps_e           : This is a print move, because we checked for X, Y, Z steps before.
      * extruder_advance_K       : There is an advance factor set.
@@ -1034,19 +1030,19 @@ Having the real displacement of the head, we can calculate the total movement le
                               && delta_mm[E_AXIS] > 0
                               && abs(delta_mm[Z_AXIS]) < 0.5;
     if (block->use_advance_lead) {
-        block->e_D_ratio = (e - position_float[E_AXIS]) /
-                           sqrt(sq(x - position_float[X_AXIS])
-                                + sq(y - position_float[Y_AXIS])
-                                + sq(z - position_float[Z_AXIS]));
+        e_D_ratio = (e - position_float[E_AXIS]) /
+                    sqrt(sq(x - position_float[X_AXIS])
+                         + sq(y - position_float[Y_AXIS])
+                         + sq(z - position_float[Z_AXIS]));
 
         // Check for unusual high e_D ratio to detect if a retract move was combined with the last
         // print move due to min. steps per segment. Never execute this with advance! This assumes
         // no one will use a retract length of 0mm < retr_length < ~0.2mm and no one will print
         // 100mm wide lines using 3mm filament or 35mm wide lines using 1.75mm filament.
-        if (block->e_D_ratio > 3.0)
+        if (e_D_ratio > 3.0)
             block->use_advance_lead = false;
         else {
-            const uint32_t max_accel_steps_per_s2 = cs.max_jerk[E_AXIS] / (extruder_advance_K * block->e_D_ratio) * steps_per_mm;
+            const uint32_t max_accel_steps_per_s2 = cs.max_jerk[E_AXIS] / (extruder_advance_K * e_D_ratio) * steps_per_mm;
             if (block->acceleration_st > max_accel_steps_per_s2) {
                 block->acceleration_st = max_accel_steps_per_s2;
                 #ifdef LA_DEBUG
@@ -1089,11 +1085,16 @@ Having the real displacement of the head, we can calculate the total movement le
 
   block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
 
-  #ifdef LIN_ADVANCE
+#ifdef LIN_ADVANCE
   if (block->use_advance_lead) {
+      // the nominal speed doesn't change past this point: calculate the compression ratio for the
+      // segment and the required advance steps
+      block->adv_comp = extruder_advance_K * e_D_ratio * cs.axis_steps_per_unit[E_AXIS];
+      block->max_adv_steps = block->nominal_speed * block->adv_comp;
+
       // to save more space we avoid another copy of calc_timer and go through slow division, but we
       // still need to replicate the *exact* same step grouping policy (see below)
-      float advance_speed = (extruder_advance_K * block->e_D_ratio * block->acceleration * cs.axis_steps_per_unit[E_AXIS]);
+      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) {
@@ -1116,7 +1117,7 @@ Having the real displacement of the head, we can calculate the total movement le
           SERIAL_ECHOLNPGM("LA: More than 2 steps per eISR loop executed.");
       #endif
   }
-  #endif
+#endif
 
   // Start with a safe speed.
   // Safe speed is the speed, from which the machine may halt to stop immediately.

+ 1 - 1
Firmware/planner.h

@@ -117,7 +117,7 @@ typedef struct {
            max_adv_steps,           // max. advance steps to get cruising speed pressure (not always nominal_speed!)
            final_adv_steps;         // advance steps due to exit speed
   uint8_t advance_step_loops;       // Number of stepper ticks for each advance isr
-  float e_D_ratio;
+  float adv_comp;                   // Precomputed E compression factor
 #endif
 
   uint16_t sdlen;

+ 2 - 1
Firmware/stepper.cpp

@@ -430,7 +430,8 @@ FORCE_INLINE void stepper_next_block()
       nextAdvanceISR = ADV_NEVER;
       e_steps = 0;
 
-      // incrementally lose pressure
+      // incrementally lose pressure to give a chance for
+      // a new LA block to be scheduled and recover
       if(current_adv_steps)
           --current_adv_steps;
 #endif