add direction control in pulsegenerator

This commit is contained in:
Nikolay Khabarov committed 2017-05-28 02:25:19 +03:00
1 parent a87e2a379b
commit ff93f526a4
5 files changed
+145 -52

No files matched your search

+50 -25
View File
@@ -42,6 +42,7 @@ class PulseGenerator(object):
self._iteration_y = 0
self._iteration_z = 0
self._iteration_e = 0
self._iteration_direction = None
self._acceleration_time_s = 0.0
self._linear_time_s = 0.0
self._2Vmax_per_a = 0.0
@@ -54,10 +55,11 @@ class PulseGenerator(object):
during movement
linear_time_s: time for uniform movement, it is total movement
time minus acceleration and braking time
max_axis_velocity_mm_per_sec: maximum velocity of any of axis during
movement. Even if whole movement is
accelerated, this value should be
calculated as top velocity.
max_axis_velocity_mm_per_sec: maximum velocity of any of axis
during movement. Even if whole
movement is accelerated, this
value should be calculated as top
velocity.
"""
raise NotImplemented
@@ -67,10 +69,13 @@ class PulseGenerator(object):
must be expressed in terms of position, i.e. t = S / V for linear,
where S - distance would be increment on motor minimum step.
:param ix: number of pulse for X axis.
:param iy: number of pulse for X axis.
:param iz: number of pulse for X axis.
:param ie: number of pulse for X axis.
:return: time for each axis or None if movement for axis is finished.
:param iy: number of pulse for Y axis.
:param iz: number of pulse for Z axis.
:param ie: number of pulse for E axis.
:return: Two tuples. First is tuple is directions for each axis,
positive means forward, negative means reverse. Second is
tuple of times for each axis in us or None if movement for
axis is finished.
"""
raise NotImplemented
@@ -87,6 +92,7 @@ class PulseGenerator(object):
self._iteration_y = 0
self._iteration_z = 0
self._iteration_e = 0
self._iteration_direction = None
logging.debug(', '.join("%s: %s" % i for i in vars(self).items()))
return self
@@ -116,7 +122,8 @@ class PulseGenerator(object):
# V on start braking is Vlinear = Taccel * a = Tbreaking * a
# Vmax * Tpseudo = Tbreaking * a * t - a * t^2 / 2
return 2.0 * self._acceleration_time_s + self._linear_time_s \
- math.sqrt(self._acceleration_time_s ** 2 - self._2Vmax_per_a * bt)
- math.sqrt(self._acceleration_time_s ** 2
- self._2Vmax_per_a * bt)
def __next__(self):
# for python3
@@ -124,14 +131,26 @@ class PulseGenerator(object):
def next(self):
""" Iterate pulses.
:return: Tuple of three values for each axis which represent time for
the next pulse. If there is no pulses left None will be
returned.
:return: Tuple of five values:
- first is boolean value, if it is True, motors direction
should be changed and next pulse should performed in
this direction.
- values for all machine axises. For direction update,
positive values means forward movement, negative value
means reverse movement. For normal pulse, values are
represent time for the next pulse in microseconds.
This iteration strictly guarantees that next pulses time will
not be earlier in time then current. If there is no pulses
left StopIteration will be raised.
"""
tx, ty, tz, te = self._interpolation_function(self._iteration_x,
self._iteration_y,
self._iteration_z,
self._iteration_e)
dir, (tx, ty, tz, te) = self._interpolation_function(self._iteration_x,
self._iteration_y,
self._iteration_z,
self._iteration_e)
# check if direction update:
if dir != self._iteration_direction:
self._iteration_direction = dir
return (True,) + dir
# check condition to stop
if tx is None and ty is None and tz is None and te is None:
raise StopIteration
@@ -165,7 +184,7 @@ class PulseGenerator(object):
te = am
self._iteration_e += 1
return tx, ty, tz, te
return False, tx, ty, tz, te
def total_time_s(self):
""" Get total time for movement.
@@ -190,23 +209,29 @@ class PulseGeneratorLinear(PulseGenerator):
velocity_mm_per_min / SECONDS_IN_MINUTE / distance_total_mm)
# acceleration time
self.acceleration_time_s = self.max_velocity_mm_per_sec.find_max() \
/ STEPPER_MAX_ACCELERATION_MM_PER_S2
/ STEPPER_MAX_ACCELERATION_MM_PER_S2
# check if there is enough space to accelerate and brake, adjust time
# S = a * t^2 / 2
if STEPPER_MAX_ACCELERATION_MM_PER_S2 * self.acceleration_time_s ** 2 \
> distance_total_mm:
self.acceleration_time_s = math.sqrt(distance_total_mm /
STEPPER_MAX_ACCELERATION_MM_PER_S2)
STEPPER_MAX_ACCELERATION_MM_PER_S2)
self.linear_time_s = 0.0
# V = a * t -> V = 2 * S / t, take half of total distance for acceleration and braking
self.max_velocity_mm_per_sec = self._distance_mm / self.acceleration_time_s
# V = a * t -> V = 2 * S / t, take half of total distance for
# acceleration and braking
self.max_velocity_mm_per_sec = self._distance_mm \
/ self.acceleration_time_s
else:
# calculate linear time
linear_distance_mm = distance_total_mm\
- self.acceleration_time_s ** 2 \
* STEPPER_MAX_ACCELERATION_MM_PER_S2
linear_distance_mm = distance_total_mm \
- self.acceleration_time_s ** 2 \
* STEPPER_MAX_ACCELERATION_MM_PER_S2
self.linear_time_s = linear_distance_mm \
/ self.max_velocity_mm_per_sec.length()
self._direction = math.copysign(1, delta_mm.x), \
math.copysign(1, delta_mm.y), \
math.copysign(1, delta_mm.z), \
math.copysign(1, delta_mm.e) \
def _get_movement_parameters(self):
""" Return movement parameters, see super class for details.
@@ -236,4 +261,4 @@ class PulseGeneratorLinear(PulseGenerator):
self.max_velocity_mm_per_sec.z)
t_e = self.__linear(ie / STEPPER_PULSES_PER_MM_E, self._distance_mm.e,
self.max_velocity_mm_per_sec.e)
return t_x, t_y, t_z, t_e
return self._direction, (t_x, t_y, t_z, t_e)