klippy: Support minimum/maximum value checks on configuration variables
Verify that numeric parameters are in a sane range when reading the config. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
7a7b98cc31
commit
7b03b04c78
|
@ -13,8 +13,10 @@ class CartKinematics:
|
||||||
self.steppers = [stepper.PrinterStepper(
|
self.steppers = [stepper.PrinterStepper(
|
||||||
printer, config.getsection('stepper_' + n), n)
|
printer, config.getsection('stepper_' + n), n)
|
||||||
for n in ['x', 'y', 'z']]
|
for n in ['x', 'y', 'z']]
|
||||||
self.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9)
|
self.max_z_velocity = config.getfloat(
|
||||||
self.max_z_accel = config.getfloat('max_z_accel', 9999999.9)
|
'max_z_velocity', 9999999.9, above=0.)
|
||||||
|
self.max_z_accel = config.getfloat(
|
||||||
|
'max_z_accel', 9999999.9, above=0.)
|
||||||
self.need_motor_enable = True
|
self.need_motor_enable = True
|
||||||
self.limits = [(1.0, -1.0)] * 3
|
self.limits = [(1.0, -1.0)] * 3
|
||||||
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
||||||
|
|
|
@ -15,8 +15,10 @@ class CoreXYKinematics:
|
||||||
for n in ['x', 'y', 'z']]
|
for n in ['x', 'y', 'z']]
|
||||||
self.steppers[0].mcu_endstop.add_stepper(self.steppers[1].mcu_stepper)
|
self.steppers[0].mcu_endstop.add_stepper(self.steppers[1].mcu_stepper)
|
||||||
self.steppers[1].mcu_endstop.add_stepper(self.steppers[0].mcu_stepper)
|
self.steppers[1].mcu_endstop.add_stepper(self.steppers[0].mcu_stepper)
|
||||||
self.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9)
|
self.max_z_velocity = config.getfloat(
|
||||||
self.max_z_accel = config.getfloat('max_z_accel', 9999999.9)
|
'max_z_velocity', 9999999.9, above=0.)
|
||||||
|
self.max_z_accel = config.getfloat(
|
||||||
|
'max_z_accel', 9999999.9, above=0.)
|
||||||
self.need_motor_enable = True
|
self.need_motor_enable = True
|
||||||
self.limits = [(1.0, -1.0)] * 3
|
self.limits = [(1.0, -1.0)] * 3
|
||||||
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
||||||
|
|
|
@ -19,8 +19,8 @@ class DeltaKinematics:
|
||||||
for n in ['a', 'b', 'c']]
|
for n in ['a', 'b', 'c']]
|
||||||
self.need_motor_enable = self.need_home = True
|
self.need_motor_enable = self.need_home = True
|
||||||
self.max_velocity = self.max_z_velocity = self.max_accel = 0.
|
self.max_velocity = self.max_z_velocity = self.max_accel = 0.
|
||||||
radius = config.getfloat('delta_radius')
|
radius = config.getfloat('delta_radius', above=0.)
|
||||||
arm_length = config.getfloat('delta_arm_length')
|
arm_length = config.getfloat('delta_arm_length', above=radius)
|
||||||
self.arm_length2 = arm_length**2
|
self.arm_length2 = arm_length**2
|
||||||
self.limit_xy2 = -1.
|
self.limit_xy2 = -1.
|
||||||
tower_height_at_zeros = math.sqrt(self.arm_length2 - radius**2)
|
tower_height_at_zeros = math.sqrt(self.arm_length2 - radius**2)
|
||||||
|
@ -53,7 +53,8 @@ class DeltaKinematics:
|
||||||
self.set_position([0., 0., 0.])
|
self.set_position([0., 0., 0.])
|
||||||
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
||||||
self.max_velocity = max_velocity
|
self.max_velocity = max_velocity
|
||||||
max_z_velocity = self.config.getfloat('max_z_velocity', max_velocity)
|
max_z_velocity = self.config.getfloat(
|
||||||
|
'max_z_velocity', max_velocity, above=0.)
|
||||||
self.max_z_velocity = min(max_velocity, max_z_velocity)
|
self.max_z_velocity = min(max_velocity, max_z_velocity)
|
||||||
self.max_accel = max_accel
|
self.max_accel = max_accel
|
||||||
for stepper in self.steppers:
|
for stepper in self.steppers:
|
||||||
|
|
|
@ -13,26 +13,32 @@ class PrinterExtruder:
|
||||||
self.config = config
|
self.config = config
|
||||||
self.heater = heater.PrinterHeater(printer, config)
|
self.heater = heater.PrinterHeater(printer, config)
|
||||||
self.stepper = stepper.PrinterStepper(printer, config, 'extruder')
|
self.stepper = stepper.PrinterStepper(printer, config, 'extruder')
|
||||||
self.nozzle_diameter = config.getfloat('nozzle_diameter')
|
self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.)
|
||||||
filament_diameter = config.getfloat('filament_diameter')
|
filament_diameter = config.getfloat(
|
||||||
|
'filament_diameter', minval=self.nozzle_diameter)
|
||||||
filament_area = math.pi * (filament_diameter * .5)**2
|
filament_area = math.pi * (filament_diameter * .5)**2
|
||||||
max_cross_section = config.getfloat(
|
max_cross_section = config.getfloat(
|
||||||
'max_extrude_cross_section', 4. * self.nozzle_diameter**2)
|
'max_extrude_cross_section', 4. * self.nozzle_diameter**2
|
||||||
|
, above=0.)
|
||||||
self.max_extrude_ratio = max_cross_section / filament_area
|
self.max_extrude_ratio = max_cross_section / filament_area
|
||||||
self.max_e_dist = config.getfloat('max_extrude_only_distance', 50.)
|
self.max_e_dist = config.getfloat(
|
||||||
|
'max_extrude_only_distance', 50., minval=0.)
|
||||||
self.max_e_velocity = self.max_e_accel = None
|
self.max_e_velocity = self.max_e_accel = None
|
||||||
self.pressure_advance = config.getfloat('pressure_advance', 0.)
|
self.pressure_advance = config.getfloat(
|
||||||
|
'pressure_advance', 0., minval=0.)
|
||||||
self.pressure_advance_lookahead_time = 0.
|
self.pressure_advance_lookahead_time = 0.
|
||||||
if self.pressure_advance:
|
if self.pressure_advance:
|
||||||
self.pressure_advance_lookahead_time = config.getfloat(
|
self.pressure_advance_lookahead_time = config.getfloat(
|
||||||
'pressure_advance_lookahead_time', 0.010)
|
'pressure_advance_lookahead_time', 0.010, minval=0.)
|
||||||
self.need_motor_enable = True
|
self.need_motor_enable = True
|
||||||
self.extrude_pos = 0.
|
self.extrude_pos = 0.
|
||||||
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
||||||
self.max_e_velocity = self.config.getfloat(
|
self.max_e_velocity = self.config.getfloat(
|
||||||
'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio)
|
'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio
|
||||||
|
, above=0.)
|
||||||
self.max_e_accel = self.config.getfloat(
|
self.max_e_accel = self.config.getfloat(
|
||||||
'max_extrude_only_accel', max_accel * self.max_extrude_ratio)
|
'max_extrude_only_accel', max_accel * self.max_extrude_ratio
|
||||||
|
, above=0.)
|
||||||
self.stepper.set_max_jerk(9999999.9, 9999999.9)
|
self.stepper.set_max_jerk(9999999.9, 9999999.9)
|
||||||
def motor_off(self, move_time):
|
def motor_off(self, move_time):
|
||||||
self.stepper.motor_enable(move_time, 0)
|
self.stepper.motor_enable(move_time, 0)
|
||||||
|
|
|
@ -11,7 +11,7 @@ class PrinterFan:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.last_fan_value = 0.
|
self.last_fan_value = 0.
|
||||||
self.last_fan_time = 0.
|
self.last_fan_time = 0.
|
||||||
self.kick_start_time = config.getfloat('kick_start_time', 0.1)
|
self.kick_start_time = config.getfloat('kick_start_time', 0.1, minval=0.)
|
||||||
pin = config.get('pin')
|
pin = config.get('pin')
|
||||||
hard_pwm = config.getint('hard_pwm', 0)
|
hard_pwm = config.getint('hard_pwm', 0)
|
||||||
self.mcu_fan = printer.mcu.create_pwm(pin, PWM_CYCLE_TIME, hard_pwm, 0.)
|
self.mcu_fan = printer.mcu.create_pwm(pin, PWM_CYCLE_TIME, hard_pwm, 0.)
|
||||||
|
|
|
@ -37,15 +37,16 @@ class PrinterHeater:
|
||||||
sensor_params = config.getchoice('sensor_type', Sensors)
|
sensor_params = config.getchoice('sensor_type', Sensors)
|
||||||
self.is_linear_sensor = (sensor_params[0] == 'linear')
|
self.is_linear_sensor = (sensor_params[0] == 'linear')
|
||||||
if self.is_linear_sensor:
|
if self.is_linear_sensor:
|
||||||
adc_voltage = config.getfloat('adc_voltage', 5.)
|
adc_voltage = config.getfloat('adc_voltage', 5., above=0.)
|
||||||
self.sensor_coef = sensor_params[1] * adc_voltage, sensor_params[2]
|
self.sensor_coef = sensor_params[1] * adc_voltage, sensor_params[2]
|
||||||
else:
|
else:
|
||||||
pullup = config.getfloat('pullup_resistor', 4700.)
|
pullup = config.getfloat('pullup_resistor', 4700., above=0.)
|
||||||
self.sensor_coef = sensor_params[1:] + (pullup,)
|
self.sensor_coef = sensor_params[1:] + (pullup,)
|
||||||
self.min_extrude_temp = config.getfloat('min_extrude_temp', 170.)
|
self.min_temp = config.getfloat('min_temp', minval=0.)
|
||||||
self.min_temp = config.getfloat('min_temp')
|
self.max_temp = config.getfloat('max_temp', above=self.min_temp)
|
||||||
self.max_temp = config.getfloat('max_temp')
|
self.min_extrude_temp = config.getfloat(
|
||||||
self.max_power = max(0., min(1., config.getfloat('max_power', 1.)))
|
'min_extrude_temp', 170., minval=self.min_temp, maxval=self.max_temp)
|
||||||
|
self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.)
|
||||||
self.can_extrude = (self.min_extrude_temp <= 0.
|
self.can_extrude = (self.min_extrude_temp <= 0.
|
||||||
or printer.mcu.is_fileoutput())
|
or printer.mcu.is_fileoutput())
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
@ -141,7 +142,7 @@ class PrinterHeater:
|
||||||
class ControlBangBang:
|
class ControlBangBang:
|
||||||
def __init__(self, heater, config):
|
def __init__(self, heater, config):
|
||||||
self.heater = heater
|
self.heater = heater
|
||||||
self.max_delta = config.getfloat('max_delta', 2.0)
|
self.max_delta = config.getfloat('max_delta', 2.0, above=0.)
|
||||||
self.heating = False
|
self.heating = False
|
||||||
def adc_callback(self, read_time, temp):
|
def adc_callback(self, read_time, temp):
|
||||||
if self.heating and temp >= self.heater.target_temp+self.max_delta:
|
if self.heating and temp >= self.heater.target_temp+self.max_delta:
|
||||||
|
@ -166,8 +167,8 @@ class ControlPID:
|
||||||
self.Kp = config.getfloat('pid_Kp') / PID_PARAM_BASE
|
self.Kp = config.getfloat('pid_Kp') / PID_PARAM_BASE
|
||||||
self.Ki = config.getfloat('pid_Ki') / PID_PARAM_BASE
|
self.Ki = config.getfloat('pid_Ki') / PID_PARAM_BASE
|
||||||
self.Kd = config.getfloat('pid_Kd') / PID_PARAM_BASE
|
self.Kd = config.getfloat('pid_Kd') / PID_PARAM_BASE
|
||||||
self.min_deriv_time = config.getfloat('pid_deriv_time', 2.)
|
self.min_deriv_time = config.getfloat('pid_deriv_time', 2., above=0.)
|
||||||
imax = config.getfloat('pid_integral_max', heater.max_power)
|
imax = config.getfloat('pid_integral_max', heater.max_power, minval=0.)
|
||||||
self.temp_integ_max = imax / self.Ki
|
self.temp_integ_max = imax / self.Ki
|
||||||
self.prev_temp = AMBIENT_TEMP
|
self.prev_temp = AMBIENT_TEMP
|
||||||
self.prev_temp_time = 0.
|
self.prev_temp_time = 0.
|
||||||
|
|
|
@ -52,26 +52,47 @@ class ConfigWrapper:
|
||||||
def __init__(self, printer, section):
|
def __init__(self, printer, section):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.section = section
|
self.section = section
|
||||||
def get_wrapper(self, parser, option, default):
|
def get_wrapper(self, parser, option, default
|
||||||
|
, minval=None, maxval=None, above=None, below=None):
|
||||||
if (default is not self.sentinel
|
if (default is not self.sentinel
|
||||||
and not self.printer.fileconfig.has_option(self.section, option)):
|
and not self.printer.fileconfig.has_option(self.section, option)):
|
||||||
return default
|
return default
|
||||||
self.printer.all_config_options[
|
self.printer.all_config_options[
|
||||||
(self.section.lower(), option.lower())] = 1
|
(self.section.lower(), option.lower())] = 1
|
||||||
try:
|
try:
|
||||||
return parser(self.section, option)
|
v = parser(self.section, option)
|
||||||
except self.error, e:
|
except self.error, e:
|
||||||
raise
|
raise
|
||||||
except:
|
except:
|
||||||
raise self.error("Unable to parse option '%s' in section '%s'" % (
|
raise self.error("Unable to parse option '%s' in section '%s'" % (
|
||||||
option, self.section))
|
option, self.section))
|
||||||
|
if minval is not None and v < minval:
|
||||||
|
raise self.error(
|
||||||
|
"Option '%s' in section '%s' must have minimum of %s" % (
|
||||||
|
option, self.section, minval))
|
||||||
|
if maxval is not None and v > maxval:
|
||||||
|
raise self.error(
|
||||||
|
"Option '%s' in section '%s' must have maximum of %s" % (
|
||||||
|
option, self.section, maxval))
|
||||||
|
if above is not None and v <= above:
|
||||||
|
raise self.error(
|
||||||
|
"Option '%s' in section '%s' must be above %s" % (
|
||||||
|
option, self.section, above))
|
||||||
|
if below is not None and v >= below:
|
||||||
|
raise self.error(
|
||||||
|
"Option '%s' in section '%s' must be below %s" % (
|
||||||
|
option, self.section, below))
|
||||||
|
return v
|
||||||
def get(self, option, default=sentinel):
|
def get(self, option, default=sentinel):
|
||||||
return self.get_wrapper(self.printer.fileconfig.get, option, default)
|
return self.get_wrapper(self.printer.fileconfig.get, option, default)
|
||||||
def getint(self, option, default=sentinel):
|
def getint(self, option, default=sentinel, minval=None, maxval=None):
|
||||||
return self.get_wrapper(self.printer.fileconfig.getint, option, default)
|
|
||||||
def getfloat(self, option, default=sentinel):
|
|
||||||
return self.get_wrapper(
|
return self.get_wrapper(
|
||||||
self.printer.fileconfig.getfloat, option, default)
|
self.printer.fileconfig.getint, option, default, minval, maxval)
|
||||||
|
def getfloat(self, option, default=sentinel
|
||||||
|
, minval=None, maxval=None, above=None, below=None):
|
||||||
|
return self.get_wrapper(
|
||||||
|
self.printer.fileconfig.getfloat, option, default
|
||||||
|
, minval, maxval, above, below)
|
||||||
def getboolean(self, option, default=sentinel):
|
def getboolean(self, option, default=sentinel):
|
||||||
return self.get_wrapper(
|
return self.get_wrapper(
|
||||||
self.printer.fileconfig.getboolean, option, default)
|
self.printer.fileconfig.getboolean, option, default)
|
||||||
|
|
|
@ -392,7 +392,8 @@ class MCU:
|
||||||
self._custom = config.get('custom', '')
|
self._custom = config.get('custom', '')
|
||||||
# Move command queuing
|
# Move command queuing
|
||||||
ffi_main, self._ffi_lib = chelper.get_ffi()
|
ffi_main, self._ffi_lib = chelper.get_ffi()
|
||||||
self._max_stepper_error = config.getfloat('max_stepper_error', 0.000025)
|
self._max_stepper_error = config.getfloat(
|
||||||
|
'max_stepper_error', 0.000025, minval=0.)
|
||||||
self._steppers = []
|
self._steppers = []
|
||||||
self._steppersync = None
|
self._steppersync = None
|
||||||
# Print time to clock epoch calculations
|
# Print time to clock epoch calculations
|
||||||
|
|
|
@ -10,19 +10,24 @@ class PrinterStepper:
|
||||||
def __init__(self, printer, config, name):
|
def __init__(self, printer, config, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
self.step_dist = config.getfloat('step_distance')
|
self.step_dist = config.getfloat('step_distance', above=0.)
|
||||||
self.inv_step_dist = 1. / self.step_dist
|
self.inv_step_dist = 1. / self.step_dist
|
||||||
self.min_stop_interval = 0.
|
self.min_stop_interval = 0.
|
||||||
|
|
||||||
self.homing_speed = config.getfloat('homing_speed', 5.0)
|
self.homing_speed = config.getfloat('homing_speed', 5.0, above=0.)
|
||||||
self.homing_positive_dir = config.getboolean(
|
self.homing_positive_dir = config.getboolean(
|
||||||
'homing_positive_dir', False)
|
'homing_positive_dir', False)
|
||||||
self.homing_retract_dist = config.getfloat('homing_retract_dist', 5.)
|
self.homing_retract_dist = config.getfloat(
|
||||||
self.homing_stepper_phases = config.getint('homing_stepper_phases', None)
|
'homing_retract_dist', 5., above=0.)
|
||||||
self.homing_endstop_phase = config.getint('homing_endstop_phase', None)
|
self.homing_stepper_phases = config.getint(
|
||||||
endstop_accuracy = config.getfloat('homing_endstop_accuracy', None)
|
'homing_stepper_phases', None, minval=0)
|
||||||
self.homing_endstop_accuracy = None
|
endstop_accuracy = config.getfloat(
|
||||||
|
'homing_endstop_accuracy', None, above=0.)
|
||||||
|
self.homing_endstop_accuracy = self.homing_endstop_phase = None
|
||||||
if self.homing_stepper_phases:
|
if self.homing_stepper_phases:
|
||||||
|
self.homing_endstop_phase = config.getint(
|
||||||
|
'homing_endstop_phase', None, minval=0
|
||||||
|
, maxval=self.homing_stepper_phases-1)
|
||||||
if endstop_accuracy is None:
|
if endstop_accuracy is None:
|
||||||
self.homing_endstop_accuracy = self.homing_stepper_phases//2 - 1
|
self.homing_endstop_accuracy = self.homing_stepper_phases//2 - 1
|
||||||
elif self.homing_endstop_phase is not None:
|
elif self.homing_endstop_phase is not None:
|
||||||
|
@ -51,8 +56,9 @@ class PrinterStepper:
|
||||||
self.mcu_endstop = mcu.create_endstop(endstop_pin)
|
self.mcu_endstop = mcu.create_endstop(endstop_pin)
|
||||||
self.mcu_endstop.add_stepper(self.mcu_stepper)
|
self.mcu_endstop.add_stepper(self.mcu_stepper)
|
||||||
self.position_min = config.getfloat('position_min', 0.)
|
self.position_min = config.getfloat('position_min', 0.)
|
||||||
|
self.position_max = config.getfloat(
|
||||||
|
'position_max', 0., above=self.position_min)
|
||||||
self.position_endstop = config.getfloat('position_endstop')
|
self.position_endstop = config.getfloat('position_endstop')
|
||||||
self.position_max = config.getfloat('position_max', 0.)
|
|
||||||
self.need_motor_enable = True
|
self.need_motor_enable = True
|
||||||
def _dist_to_time(self, dist, start_velocity, accel):
|
def _dist_to_time(self, dist, start_velocity, accel):
|
||||||
# Calculate the time it takes to travel a distance with constant accel
|
# Calculate the time it takes to travel a distance with constant accel
|
||||||
|
|
|
@ -188,18 +188,24 @@ class ToolHead:
|
||||||
'corexy': corexy.CoreXYKinematics,
|
'corexy': corexy.CoreXYKinematics,
|
||||||
'delta': delta.DeltaKinematics}
|
'delta': delta.DeltaKinematics}
|
||||||
self.kin = config.getchoice('kinematics', kintypes)(printer, config)
|
self.kin = config.getchoice('kinematics', kintypes)(printer, config)
|
||||||
self.max_speed = config.getfloat('max_velocity')
|
self.max_speed = config.getfloat('max_velocity', above=0.)
|
||||||
self.max_accel = config.getfloat('max_accel')
|
self.max_accel = config.getfloat('max_accel', above=0.)
|
||||||
self.max_accel_to_decel = config.getfloat('max_accel_to_decel'
|
self.max_accel_to_decel = config.getfloat(
|
||||||
, self.max_accel * 0.5)
|
'max_accel_to_decel', self.max_accel * 0.5
|
||||||
self.junction_deviation = config.getfloat('junction_deviation', 0.02)
|
, above=0., maxval=self.max_accel)
|
||||||
|
self.junction_deviation = config.getfloat(
|
||||||
|
'junction_deviation', 0.02, above=0.)
|
||||||
self.move_queue = MoveQueue(self.extruder.lookahead)
|
self.move_queue = MoveQueue(self.extruder.lookahead)
|
||||||
self.commanded_pos = [0., 0., 0., 0.]
|
self.commanded_pos = [0., 0., 0., 0.]
|
||||||
# Print time tracking
|
# Print time tracking
|
||||||
self.buffer_time_high = config.getfloat('buffer_time_high', 2.000)
|
self.buffer_time_low = config.getfloat(
|
||||||
self.buffer_time_low = config.getfloat('buffer_time_low', 1.000)
|
'buffer_time_low', 1.000, above=0.)
|
||||||
self.buffer_time_start = config.getfloat('buffer_time_start', 0.250)
|
self.buffer_time_high = config.getfloat(
|
||||||
self.move_flush_time = config.getfloat('move_flush_time', 0.050)
|
'buffer_time_high', 2.000, above=self.buffer_time_low)
|
||||||
|
self.buffer_time_start = config.getfloat(
|
||||||
|
'buffer_time_start', 0.250, above=0.)
|
||||||
|
self.move_flush_time = config.getfloat(
|
||||||
|
'move_flush_time', 0.050, above=0.)
|
||||||
self.print_time = 0.
|
self.print_time = 0.
|
||||||
self.need_check_stall = -1.
|
self.need_check_stall = -1.
|
||||||
self.print_stall = 0
|
self.print_stall = 0
|
||||||
|
@ -208,7 +214,8 @@ class ToolHead:
|
||||||
self.flush_timer = self.reactor.register_timer(self._flush_handler)
|
self.flush_timer = self.reactor.register_timer(self._flush_handler)
|
||||||
self.move_queue.set_flush_time(self.buffer_time_high)
|
self.move_queue.set_flush_time(self.buffer_time_high)
|
||||||
# Motor off tracking
|
# Motor off tracking
|
||||||
self.motor_off_time = config.getfloat('motor_off_time', 600.000)
|
self.motor_off_time = config.getfloat(
|
||||||
|
'motor_off_time', 600.000, minval=0.)
|
||||||
self.motor_off_timer = self.reactor.register_timer(
|
self.motor_off_timer = self.reactor.register_timer(
|
||||||
self._motor_off_handler)
|
self._motor_off_handler)
|
||||||
# Determine the maximum velocity a cartesian axis could have
|
# Determine the maximum velocity a cartesian axis could have
|
||||||
|
|
Loading…
Reference in New Issue