Skip to content

Commit

Permalink
add klippy tests and apply linting
Browse files Browse the repository at this point in the history
  • Loading branch information
rogerlz committed Jan 9, 2024
1 parent 1b5adb5 commit 5820a19
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 22 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ Our goal is to support features and behavior that could be "risky" if used incor
If I want my printer to light itself on fire, I should be able to make my printer light itself on fire.

## Features merged into the master branch:
- [heater: Dual Loop PID](https://github.com/DangerKlippers/danger-klipper/issues/58) ([klipper#5972](https://github.com/Klipper3d/klipper/pull/5972))

- [core: no Python2 tests; no PRU boards](https://github.com/DangerKlippers/danger-klipper/pull/39)

Expand All @@ -23,6 +22,8 @@ If I want my printer to light itself on fire, I should be able to make my printe

- [heater: velocity PID](https://github.com/DangerKlippers/danger-klipper/pull/47) ([klipper#6272](https://github.com/Klipper3d/klipper/pull/6272))

- [heater: Dual Loop PID](https://github.com/DangerKlippers/danger-klipper/issues/58) ([klipper#5972](https://github.com/Klipper3d/klipper/pull/5972))

- [gcode: jinja2.ext.do extension](https://github.com/DangerKlippers/danger-klipper/pull/26) ([klipper#5149](https://github.com/Klipper3d/klipper/pull/5149))

- [gcode: gcode_shell_command](https://github.com/DangerKlippers/danger-klipper/pull/26) ([klipper#2173](https://github.com/Klipper3d/klipper/pull/2173) / [kiuah](https://github.com/dw-0/kiauh/blob/master/resources/gcode_shell_command.py) )
Expand Down
72 changes: 51 additions & 21 deletions klippy/extras/pid_calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ def __init__(self, config):
cmd_PID_CALIBRATE_help = "Run PID calibration test"

def _calibrate(
self, pheaters, heater, target, tolerance, fname, gcmd,
calibrate_secondary
self,
pheaters,
heater,
target,
tolerance,
fname,
gcmd,
calibrate_secondary,
):
if (
isinstance(heater.control, heaters.ControlDualLoopPID)
and calibrate_secondary
isinstance(heater.control, heaters.ControlDualLoopPID)
and calibrate_secondary
):
sec_target = heater.control.sec_max_temp_target
calibrate = ControlAutoTune(
Expand All @@ -37,8 +43,8 @@ def _calibrate(
calibrate_secondary=calibrate_secondary,
)
elif (
isinstance(heater.control, heaters.ControlDualLoopPID)
and not calibrate_secondary
isinstance(heater.control, heaters.ControlDualLoopPID)
and not calibrate_secondary
):
calibrate = ControlAutoTune(
heater,
Expand All @@ -48,9 +54,7 @@ def _calibrate(
calibrate_secondary=calibrate_secondary,
)
else:
calibrate = ControlAutoTune(heater,
target,
tolerance)
calibrate = ControlAutoTune(heater, target, tolerance)

old_control = heater.set_control(calibrate)
try:
Expand Down Expand Up @@ -84,7 +88,13 @@ def cmd_PID_CALIBRATE(self, gcmd):
if isinstance(heater.control, heaters.ControlDualLoopPID):
fname = "/tmp/heattest_secondary.txt" if write_file else None
kp_s, ki_s, kd_s, _ = self._calibrate(
pheaters, heater, target, tolerance, fname, gcmd, calibrate_secondary=True
pheaters,
heater,
target,
tolerance,
fname,
gcmd,
calibrate_secondary=True,
)
old_kp = heater.control.secondary_pid.Kp
old_ki = heater.control.secondary_pid.Ki
Expand All @@ -95,7 +105,13 @@ def cmd_PID_CALIBRATE(self, gcmd):
fname = "/tmp/heattest_primary.txt" if write_file else None

kp_p, ki_p, kd_p, _ = self._calibrate(
pheaters, heater, target, tolerance, fname, gcmd, calibrate_secondary=False
pheaters,
heater,
target,
tolerance,
fname,
gcmd,
calibrate_secondary=False,
)

heater.control.secondary_pid.kp = old_kp
Expand All @@ -122,7 +138,13 @@ def cmd_PID_CALIBRATE(self, gcmd):
else:
fname = "/tmp/heattest.txt" if write_file else None
Kp, Ki, Kd, old_control = self._calibrate(
pheaters, heater, target, tolerance, fname, gcmd, calibrate_secondary=False
pheaters,
heater,
target,
tolerance,
fname,
gcmd,
calibrate_secondary=False,
)
logging.info("Autotune: final: Kp=%f Ki=%f Kd=%f", Kp, Ki, Kd)
gcmd.respond_info(
Expand All @@ -146,7 +168,9 @@ def cmd_PID_CALIBRATE(self, gcmd):


class ControlAutoTune:
def __init__(self, heater, target, tolerance, control=None, calibrate_secondary=False):
def __init__(
self, heater, target, tolerance, control=None, calibrate_secondary=False
):
self.heater = heater
self.heater_max_power = heater.get_max_power()
# store the reference so we can push messages if needed
Expand Down Expand Up @@ -186,8 +210,9 @@ def __init__(self, heater, target, tolerance, control=None, calibrate_secondary=
self._control = control
self._calibrate_secondary = calibrate_secondary

def temperature_update(self, read_time, primary_temp, target_temp,
secondary_temp=None):
def temperature_update(
self, read_time, primary_temp, target_temp, secondary_temp=None
):

if self._calibrate_secondary:
ref_temp = secondary_temp
Expand All @@ -202,7 +227,11 @@ def temperature_update(self, read_time, primary_temp, target_temp,
(read_time, ref_temp, self.heater.last_pwm_value, self.target)
)
# ensure the starting temp is low enough to run the test.
if not self.started and ref_temp >= self.temp_low and self._control is None:
if (
not self.started
and ref_temp >= self.temp_low
and self._control is None
):
self.errored = True
self.finish(read_time)
self.gcode.respond_info("temperature to high to start calibration")
Expand Down Expand Up @@ -254,8 +283,9 @@ def temperature_update(self, read_time, primary_temp, target_temp,
if self._control is not None and not self._calibrate_secondary:
pid = self._control.secondary_pid
sec_target = self._control.sec_max_temp_target
_, bounded_co = pid.calculate_output(read_time, secondary_temp,
sec_target)
_, bounded_co = pid.calculate_output(
read_time, secondary_temp, sec_target
)
bounded_co = min(bounded_co, self.powers[-1])
self.heater.set_pwm(read_time, bounded_co)
else:
Expand Down Expand Up @@ -301,7 +331,7 @@ def get_sample_tolerance(self):
powers = len(self.powers)
if powers < TUNE_PID_SAMPLES + 1:
return False
powers = self.powers[-1 * (TUNE_PID_SAMPLES + 1):]
powers = self.powers[-1 * (TUNE_PID_SAMPLES + 1) :]
return max(powers) - min(powers)

def converged(self):
Expand Down Expand Up @@ -383,14 +413,14 @@ def calc_pid(self):
time_diff = time_diff / float(TUNE_PID_SAMPLES)
theta = theta / float(TUNE_PID_SAMPLES)
amplitude = 0.5 * abs(temp_diff)
power = self.powers[-1 * (TUNE_PID_SAMPLES):]
power = self.powers[-1 * (TUNE_PID_SAMPLES) :]
power = sum(power) / float(len(power))
# calculate the various parameters
Ku = 4.0 * power / (math.pi * amplitude)
Tu = time_diff
Wu = (2.0 * math.pi) / Tu
tau = math.tan(math.pi - theta * Wu) / Wu
Km = -math.sqrt(tau ** 2 * Wu ** 2 + 1.0) / Ku
Km = -math.sqrt(tau**2 * Wu**2 + 1.0) / Ku
# log the extra details
logging.info("Ziegler-Nichols constants: Ku=%f Tu=%f", Ku, Tu)
logging.info(
Expand Down
80 changes: 80 additions & 0 deletions test/klippy/dual_loop_pid.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Config for extruder testing
[stepper_x]
step_pin: PF0
dir_pin: PF1
enable_pin: !PD7
microsteps: 16
rotation_distance: 40
endstop_pin: ^PE5
position_endstop: 0
position_max: 200
homing_speed: 50

[stepper_y]
step_pin: PF6
dir_pin: !PF7
enable_pin: !PF2
microsteps: 16
rotation_distance: 40
endstop_pin: ^PJ1
position_endstop: 0
position_max: 200
homing_speed: 50

[stepper_z]
step_pin: PL3
dir_pin: PL1
enable_pin: !PK0
microsteps: 16
rotation_distance: 8
endstop_pin: ^PD3
position_endstop: 0.5
position_max: 200

[temperature_sensor myExtraSensor]
sensor_type: Generic 3950
sensor_pin: PF4
min_temp: 0
max_temp: 80

[extruder]
step_pin: PA4
dir_pin: PA6
enable_pin: !PA2
microsteps: 16
rotation_distance: 33.5
nozzle_diameter: 0.500
filament_diameter: 3.500
heater_pin: PB4
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PK5
min_temp: 0
max_temp: 400

secondary_sensor_name: myExtraSensor
secondary_max_temp_target: 280
control: dual_loop_pid
primary_pid_kp: 22.2
primary_pid_ki: 1.08
primary_pid_kd: 114
secondary_pid_kp: 22.2
secondary_pid_ki: 1.08
secondary_pid_kd: 114

[extruder_stepper my_extra_stepper]
extruder: extruder
step_pin: PH5
dir_pin: PH6
enable_pin: !PB5
microsteps: 16
rotation_distance: 28.2

[mcu]
serial: /dev/ttyACM0

[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
13 changes: 13 additions & 0 deletions test/klippy/dual_loop_pid.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Pid hot modify tests
DICTIONARY atmega2560.dict
CONFIG dual_loop_pid.cfg

# Extrude only
G1 E5
G1 E-2
G1 E7

# Home and extrusion moves
G28
G1 X20 Y20 Z1
G1 X25 Y25 E7.5

0 comments on commit 5820a19

Please sign in to comment.