Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeanon committed Oct 15, 2023
1 parent 442d476 commit 5cbed52
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 37 deletions.
24 changes: 17 additions & 7 deletions docs/G-Codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -989,15 +989,20 @@ in the config file.

#### PID_PROFILE
`PID_PROFILE LOAD=<profile_name> HEATER=<config_name> [DEFAULT=<profile_name>]
[VERBOSE=<verbosity>] [RESET_TARGET=0|1]`:
[VERBOSE=<verbosity>] [RESET_TARGET=0|1] [LOAD_CLEAN=0|1]`:
Loads the given PID_PROFILE for the specified heater. If DEFAULT is specified,
the Profile specified in DEFAULT will be loaded when then given Profile for LOAD
can't be found (like a getOrDefault method). If VERBOSE is set to LOW, minimal
info will be written in console.
If set to NONE, no console outputs will be given.
If RESET_TARGET is set to 1, the target temperature of the heater will be set
to 0 when changing profiles.
By default the target temperature of the heater will not be reset.
If KEEP_TARGET is set to 1, the heater will keep it's target temperature,
if set to 0, the target temperature will be set to 0.
By default the target temperature of the heater will be set to 0 so the
algorithm has time to settle in.
If LOAD_CLEAN is set to 1, the profile would be loaded as if the printer just
started up, if set to 0, the profile will retain previous heating information.
By default the information will be kept to reduce overshoot, change this value
if you encounter weird behaviour while switching profiles.

`PID_PROFILE SAVE=<profile_name> HEATER=<config_name>`:
Saves the currently loaded profile of the specified heater to the config under
Expand All @@ -1011,9 +1016,14 @@ CONTROL=<control_type> KP=<kp> KI=<ki> KD=<kd> [RESET_TARGET=0|1]`:
Creates a new profile with the given PID values, CONTROL must either be `pid` or
`pid_v`, TOLERANCE and TARGET must be specified to create a valid profile,
though the values themselves don't matter.
If RESET_TARGET is set to 1, the target temperature of the heater will be set
to 0 when setting the values.
By default the target temperature of the heater will not be reset.
If KEEP_TARGET is set to 1, the heater will keep it's target temperature,
if set to 0, the target temperature will be set to 0.
By default the target temperature of the heater will be set to 0 so the
algorithm has time to settle in.
If LOAD_CLEAN is set to 1, the profile would be loaded as if the printer just
started up, if set to 0, the profile will retain previous heating information.
By default the information will be kept to reduce overshoot, change this value
if you encounter weird behaviour while switching profiles.



Expand Down
85 changes: 58 additions & 27 deletions klippy/extras/heaters.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def __init__(self, config, sensor):
self.pmgr.cmd_PID_PROFILE,
desc=
self.pmgr.cmd_PID_PROFILE_help)
def lookup_control(self, profile, reset_temp=True):
def lookup_control(self, profile, load_clean=True):
algos = collections.OrderedDict({
'watermark': ControlBangBang,
'pid': ControlPID,
Expand All @@ -110,7 +110,7 @@ def lookup_control(self, profile, reset_temp=True):
return algos[profile['control']](profile,
self,
None
if reset_temp else
if load_clean else
self.get_temp(self.reactor.monotonic())
)
def set_pwm(self, read_time, value):
Expand Down Expand Up @@ -165,11 +165,11 @@ def check_busy(self, eventtime):
with self.lock:
return self.control.check_busy(
eventtime, self.smoothed_temp, self.target_temp)
def set_control(self, control, reset_target=False):
def set_control(self, control, keep_target=True):
with self.lock:
old_control = self.control
self.control = control
if reset_target:
if not keep_target:
self.target_temp = 0.
return old_control
def get_control(self):
Expand Down Expand Up @@ -294,11 +294,24 @@ def _compute_section_name(self, profile_name):
+ " "
+ profile_name)
)
def _check_value_gcmd(self, name, default, gcmd, type, can_be_none):
def _check_value_gcmd(self,
name,
default,
gcmd,
type,
can_be_none,
minval=None,
maxval=None, ):
if type is int:
value = gcmd.get_int(name, default)
value = gcmd.get_int(name,
default,
minval=minval,
maxval=maxval)
elif type is float:
value = gcmd.get_float(name, default)
value = gcmd.get_float(name,
default,
minval=minval,
maxval=maxval)
else:
value = gcmd.get(name, default)
if not can_be_none and value is None:
Expand Down Expand Up @@ -347,11 +360,20 @@ def set_values(self, profile_name, gcmd, verbose):
gcmd,
float,
True)
reset_target = self._check_value_gcmd('RESET_TARGET',
0,
gcmd,
int,
False)
keep_target = self._check_value_gcmd('KEEP_TARGET',
0,
gcmd,
int,
True,
minval=0,
maxval=1)
load_clean = self._check_value_gcmd('LOAD_CLEAN',
0,
gcmd,
int,
True,
minval=0,
maxval=1)
temp_profile = {'pid_target': target,
'pid_tolerance': tolerance,
'control': control,
Expand All @@ -360,8 +382,8 @@ def set_values(self, profile_name, gcmd, verbose):
'pid_ki': ki,
'pid_kd': kd}
temp_control = self.outer_instance.lookup_control(temp_profile,
False)
self.outer_instance.set_control(temp_control, reset_target)
load_clean)
self.outer_instance.set_control(temp_control, keep_target)
msg = ("PID Parameters:\n"
"Target: %.2f,\n"
"Tolerance: %.4f\n"
Expand Down Expand Up @@ -427,21 +449,30 @@ def load_profile(self, profile_name, gcmd, verbose):
gcmd,
'lower',
True)
load_clean = self._check_value_gcmd('LOAD_CLEAN',
0,
gcmd,
int,
True,
minval=0,
maxval=1)
if (profile_name
==
self.outer_instance.get_control().get_profile()['name']
and
(verbose == 'high' or verbose == 'low')):
self.outer_instance.gcode.respond_info(
"PID Profile [%s] already loaded for heater [%s]."
% (profile_name, self.outer_instance.name)
)
and not load_clean):
if verbose == 'high' or verbose == 'low':
self.outer_instance.gcode.respond_info(
"PID Profile [%s] already loaded for heater [%s]."
% (profile_name, self.outer_instance.name)
)
return
reset_target = self._check_value_gcmd('RESET_TARGET',
0,
gcmd,
int,
True)
keep_target = self._check_value_gcmd('KEEP_TARGET',
0,
gcmd,
int,
True,
minval=0,
maxval=1)
profile = self.profiles.get(profile_name, None)
defaulted = False
default = gcmd.get('DEFAULT', None)
Expand All @@ -460,8 +491,8 @@ def load_profile(self, profile_name, gcmd, verbose):
% (default,
self.outer_instance.name)
)
control = self.outer_instance.lookup_control(profile, False)
self.outer_instance.set_control(control, reset_target)
control = self.outer_instance.lookup_control(profile, load_clean)
self.outer_instance.set_control(control, keep_target)

if verbose != 'high' and verbose != 'low':
return
Expand Down
6 changes: 3 additions & 3 deletions klippy/extras/pid_calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ def cmd_PID_CALIBRATE(self, gcmd):
raise gcmd.error(str(e))
self.printer.lookup_object('toolhead').get_last_move_time()
calibrate = ControlAutoTune(heater, target, tolerance, tune_pid_delta)
old_control = heater.set_control(calibrate, True)
old_control = heater.set_control(calibrate, False)
try:
pheaters.set_temperature(heater, target, True)
except self.printer.command_error as e:
heater.set_control(old_control, True)
heater.set_control(old_control, False)
raise
if write_file:
calibrate.write_file('/tmp/heattest.csv')
Expand All @@ -58,7 +58,7 @@ def cmd_PID_CALIBRATE(self, gcmd):
'smooth_time': None,
'name': profile_name}

heater.set_control(heater.lookup_control(profile, True), True)
heater.set_control(heater.lookup_control(profile, True), False)
heater.pmgr.save_profile(profile_name=profile_name, verbose=False)

TUNE_PID_TOL = 0.02
Expand Down

0 comments on commit 5cbed52

Please sign in to comment.