From df6d3107f2b9948bc9dc28c4a1dd6a9ea9fda0fe Mon Sep 17 00:00:00 2001
From: Kevin O'Connor <kevin@koconnor.net>
Date: Wed, 15 Mar 2017 23:08:29 -0400
Subject: [PATCH] stepper: Fix set_min_stop_interval() calculation

The previous calculation was only valid if the stepper is always
commanded to a position that is an exact multiple of the
step_distance.  The safety check was programmed with a value too large
for other commanded positions, which could result in "No next step"
errors.  Fix by changing the calculation to use the worst case
scenario.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
---
 klippy/stepper.py | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/klippy/stepper.py b/klippy/stepper.py
index 6917afa91..32a17c2bc 100644
--- a/klippy/stepper.py
+++ b/klippy/stepper.py
@@ -50,11 +50,17 @@ class PrinterStepper:
             self.position_endstop = config.getfloat('position_endstop')
             self.position_max = config.getfloat('position_max', 0.)
         self.need_motor_enable = True
+    def _dist_to_time(self, dist, start_velocity, accel):
+        # Calculate the time it takes to travel a distance with constant accel
+        time_offset = start_velocity / accel
+        return math.sqrt(2. * dist / accel + time_offset**2) - time_offset
     def set_max_jerk(self, max_halt_velocity, max_accel):
-        jc = max_halt_velocity / max_accel
-        inv_max_step_accel = self.step_dist / max_accel
-        min_stop_interval = (math.sqrt(3.*inv_max_step_accel + jc**2)
-                             - math.sqrt(inv_max_step_accel + jc**2))
+        # Calculate the firmware's maximum halt interval time
+        last_step_time = self._dist_to_time(
+            self.step_dist, max_halt_velocity, max_accel)
+        second_last_step_time = self._dist_to_time(
+            2. * self.step_dist, max_halt_velocity, max_accel)
+        min_stop_interval = second_last_step_time - last_step_time
         self.mcu_stepper.set_min_stop_interval(min_stop_interval)
     def motor_enable(self, move_time, enable=0):
         if enable and self.need_motor_enable: