From 7b03b04c786863bc32d3b790862857061f71f072 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 11 Apr 2017 11:37:09 -0400 Subject: [PATCH] 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 --- klippy/cartesian.py | 6 ++++-- klippy/corexy.py | 6 ++++-- klippy/delta.py | 7 ++++--- klippy/extruder.py | 22 ++++++++++++++-------- klippy/fan.py | 2 +- klippy/heater.py | 19 ++++++++++--------- klippy/klippy.py | 33 +++++++++++++++++++++++++++------ klippy/mcu.py | 3 ++- klippy/stepper.py | 22 ++++++++++++++-------- klippy/toolhead.py | 27 +++++++++++++++++---------- 10 files changed, 97 insertions(+), 50 deletions(-) diff --git a/klippy/cartesian.py b/klippy/cartesian.py index ab95df5d..f69855f6 100644 --- a/klippy/cartesian.py +++ b/klippy/cartesian.py @@ -13,8 +13,10 @@ class CartKinematics: self.steppers = [stepper.PrinterStepper( printer, config.getsection('stepper_' + n), n) for n in ['x', 'y', 'z']] - self.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9) - self.max_z_accel = config.getfloat('max_z_accel', 9999999.9) + self.max_z_velocity = config.getfloat( + '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.limits = [(1.0, -1.0)] * 3 def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel): diff --git a/klippy/corexy.py b/klippy/corexy.py index dfee7bb3..d429496c 100644 --- a/klippy/corexy.py +++ b/klippy/corexy.py @@ -15,8 +15,10 @@ class CoreXYKinematics: for n in ['x', 'y', 'z']] 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.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9) - self.max_z_accel = config.getfloat('max_z_accel', 9999999.9) + self.max_z_velocity = config.getfloat( + '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.limits = [(1.0, -1.0)] * 3 def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel): diff --git a/klippy/delta.py b/klippy/delta.py index ac8d025f..62074d7a 100644 --- a/klippy/delta.py +++ b/klippy/delta.py @@ -19,8 +19,8 @@ class DeltaKinematics: for n in ['a', 'b', 'c']] self.need_motor_enable = self.need_home = True self.max_velocity = self.max_z_velocity = self.max_accel = 0. - radius = config.getfloat('delta_radius') - arm_length = config.getfloat('delta_arm_length') + radius = config.getfloat('delta_radius', above=0.) + arm_length = config.getfloat('delta_arm_length', above=radius) self.arm_length2 = arm_length**2 self.limit_xy2 = -1. tower_height_at_zeros = math.sqrt(self.arm_length2 - radius**2) @@ -53,7 +53,8 @@ class DeltaKinematics: self.set_position([0., 0., 0.]) def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel): 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_accel = max_accel for stepper in self.steppers: diff --git a/klippy/extruder.py b/klippy/extruder.py index 24153e0f..ee46bead 100644 --- a/klippy/extruder.py +++ b/klippy/extruder.py @@ -13,26 +13,32 @@ class PrinterExtruder: self.config = config self.heater = heater.PrinterHeater(printer, config) self.stepper = stepper.PrinterStepper(printer, config, 'extruder') - self.nozzle_diameter = config.getfloat('nozzle_diameter') - filament_diameter = config.getfloat('filament_diameter') + self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.) + filament_diameter = config.getfloat( + 'filament_diameter', minval=self.nozzle_diameter) filament_area = math.pi * (filament_diameter * .5)**2 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_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.pressure_advance = config.getfloat('pressure_advance', 0.) + self.pressure_advance = config.getfloat( + 'pressure_advance', 0., minval=0.) self.pressure_advance_lookahead_time = 0. if self.pressure_advance: 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.extrude_pos = 0. def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel): 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( - '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) def motor_off(self, move_time): self.stepper.motor_enable(move_time, 0) diff --git a/klippy/fan.py b/klippy/fan.py index 78767b02..9b78d6ab 100644 --- a/klippy/fan.py +++ b/klippy/fan.py @@ -11,7 +11,7 @@ class PrinterFan: def __init__(self, printer, config): self.last_fan_value = 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') hard_pwm = config.getint('hard_pwm', 0) self.mcu_fan = printer.mcu.create_pwm(pin, PWM_CYCLE_TIME, hard_pwm, 0.) diff --git a/klippy/heater.py b/klippy/heater.py index 8de546b5..c4e0a715 100644 --- a/klippy/heater.py +++ b/klippy/heater.py @@ -37,15 +37,16 @@ class PrinterHeater: sensor_params = config.getchoice('sensor_type', Sensors) self.is_linear_sensor = (sensor_params[0] == 'linear') 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] else: - pullup = config.getfloat('pullup_resistor', 4700.) + pullup = config.getfloat('pullup_resistor', 4700., above=0.) self.sensor_coef = sensor_params[1:] + (pullup,) - self.min_extrude_temp = config.getfloat('min_extrude_temp', 170.) - self.min_temp = config.getfloat('min_temp') - self.max_temp = config.getfloat('max_temp') - self.max_power = max(0., min(1., config.getfloat('max_power', 1.))) + self.min_temp = config.getfloat('min_temp', minval=0.) + self.max_temp = config.getfloat('max_temp', above=self.min_temp) + self.min_extrude_temp = config.getfloat( + '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. or printer.mcu.is_fileoutput()) self.lock = threading.Lock() @@ -141,7 +142,7 @@ class PrinterHeater: class ControlBangBang: def __init__(self, heater, config): 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 def adc_callback(self, read_time, temp): 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.Ki = config.getfloat('pid_Ki') / PID_PARAM_BASE self.Kd = config.getfloat('pid_Kd') / PID_PARAM_BASE - self.min_deriv_time = config.getfloat('pid_deriv_time', 2.) - imax = config.getfloat('pid_integral_max', heater.max_power) + self.min_deriv_time = config.getfloat('pid_deriv_time', 2., above=0.) + imax = config.getfloat('pid_integral_max', heater.max_power, minval=0.) self.temp_integ_max = imax / self.Ki self.prev_temp = AMBIENT_TEMP self.prev_temp_time = 0. diff --git a/klippy/klippy.py b/klippy/klippy.py index 0ecdb0a7..e63bb096 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -52,26 +52,47 @@ class ConfigWrapper: def __init__(self, printer, section): self.printer = printer 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 and not self.printer.fileconfig.has_option(self.section, option)): return default self.printer.all_config_options[ (self.section.lower(), option.lower())] = 1 try: - return parser(self.section, option) + v = parser(self.section, option) except self.error, e: raise except: raise self.error("Unable to parse option '%s' in section '%s'" % ( 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): return self.get_wrapper(self.printer.fileconfig.get, option, default) - def getint(self, option, default=sentinel): - return self.get_wrapper(self.printer.fileconfig.getint, option, default) - def getfloat(self, option, default=sentinel): + def getint(self, option, default=sentinel, minval=None, maxval=None): 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): return self.get_wrapper( self.printer.fileconfig.getboolean, option, default) diff --git a/klippy/mcu.py b/klippy/mcu.py index 5b12e83f..50a0eab4 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -392,7 +392,8 @@ class MCU: self._custom = config.get('custom', '') # Move command queuing 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._steppersync = None # Print time to clock epoch calculations diff --git a/klippy/stepper.py b/klippy/stepper.py index 5bdcb374..a2fda545 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -10,19 +10,24 @@ class PrinterStepper: def __init__(self, printer, config, 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.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( 'homing_positive_dir', False) - self.homing_retract_dist = config.getfloat('homing_retract_dist', 5.) - self.homing_stepper_phases = config.getint('homing_stepper_phases', None) - self.homing_endstop_phase = config.getint('homing_endstop_phase', None) - endstop_accuracy = config.getfloat('homing_endstop_accuracy', None) - self.homing_endstop_accuracy = None + self.homing_retract_dist = config.getfloat( + 'homing_retract_dist', 5., above=0.) + self.homing_stepper_phases = config.getint( + 'homing_stepper_phases', None, minval=0) + endstop_accuracy = config.getfloat( + 'homing_endstop_accuracy', None, above=0.) + self.homing_endstop_accuracy = self.homing_endstop_phase = None 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: self.homing_endstop_accuracy = self.homing_stepper_phases//2 - 1 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.add_stepper(self.mcu_stepper) 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_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 diff --git a/klippy/toolhead.py b/klippy/toolhead.py index d7b677ce..bd4ccd10 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -188,18 +188,24 @@ class ToolHead: 'corexy': corexy.CoreXYKinematics, 'delta': delta.DeltaKinematics} self.kin = config.getchoice('kinematics', kintypes)(printer, config) - self.max_speed = config.getfloat('max_velocity') - self.max_accel = config.getfloat('max_accel') - self.max_accel_to_decel = config.getfloat('max_accel_to_decel' - , self.max_accel * 0.5) - self.junction_deviation = config.getfloat('junction_deviation', 0.02) + self.max_speed = config.getfloat('max_velocity', above=0.) + self.max_accel = config.getfloat('max_accel', above=0.) + self.max_accel_to_decel = config.getfloat( + 'max_accel_to_decel', self.max_accel * 0.5 + , 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.commanded_pos = [0., 0., 0., 0.] # Print time tracking - self.buffer_time_high = config.getfloat('buffer_time_high', 2.000) - self.buffer_time_low = config.getfloat('buffer_time_low', 1.000) - self.buffer_time_start = config.getfloat('buffer_time_start', 0.250) - self.move_flush_time = config.getfloat('move_flush_time', 0.050) + self.buffer_time_low = config.getfloat( + 'buffer_time_low', 1.000, above=0.) + self.buffer_time_high = config.getfloat( + '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.need_check_stall = -1. self.print_stall = 0 @@ -208,7 +214,8 @@ class ToolHead: self.flush_timer = self.reactor.register_timer(self._flush_handler) self.move_queue.set_flush_time(self.buffer_time_high) # 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_handler) # Determine the maximum velocity a cartesian axis could have