diff --git a/docs/G-Codes.md b/docs/G-Codes.md index 70e3abe2..4d40956f 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -212,18 +212,33 @@ The following standard commands are supported: babystepping), and subtract it from the stepper_z endstop_position. This acts to take a frequently used babystepping value, and "make it permanent". Requires a `SAVE_CONFIG` to take effect. -- `TUNING_TOWER COMMAND= PARAMETER= START= - FACTOR= [BAND=] [SKIP=]`: A tool for tuning - a parameter on each Z height during a print. The tool will run - the given COMMAND with the given PARAMETER assigned to the value - using the formula `value = start + factor * z_height`. If BAND is - provided then the adjustment will only be made every BAND - millimeters of z height - in that case the formula used is - `value = start + factor * ((floor(z_height / band) + .5) * band)`. - If `SKIP=` is specified, the tuning process doesn't begin - until Z height `` is reached, and below that the value will - be set to `START`; in this case, the `z_height` used in the - formulas above is actually `max(z - skip, 0)`. +- `TUNING_TOWER COMMAND= PARAMETER= START= [SKIP=] + [FACTOR= [BAND=]] | [STEP_DELTA= STEP_HEIGHT=]`: + A tool for tuning a parameter on each Z height during a print. + The tool will run the given `COMMAND` with the given `PARAMETER` + assigned to a value that varies with `Z` according to a formula. Use `FACTOR` + if you will use a ruler or calipers to measure the Z height of the optimum + value, or `STEP_DELTA` and `STEP_HEIGHT` if the tuning tower model has bands + of discrete values as is common with temperature towers. If `SKIP=` + is specified, the tuning process doesn't begin until Z height `` is + reached, and below that the value will be set to `START`; in this case, the + `z_height` used in the formulas below is actually `max(z - skip, 0)`. + There are three possible combinations of options: + - `FACTOR`: The value changes at a rate of `factor` per millimeter. + The formula used is + `value = start + factor * z_height`. + You can plug the optimum Z height directly into the formula to + determine the optimum parameter value. + - `FACTOR` and `BAND`: The value changes at an average rate of `factor` per + millimeter, but in discrete bands where the adjustment will only be made + every `BAND` millimeters of Z height. + The formula used is + `value = start + factor * ((floor(z_height / band) + .5) * band)`. + - `STEP_DELTA` and `STEP_HEIGHT`: The value changes by `STEP_DELTA` every + `STEP_HEIGHT` millimeters. The formula used is + `value = start + step_delta * floor(z_height / step_height)`. + You can simply count bands or read tuning tower labels to determine the + optimum value. - `SET_DISPLAY_GROUP [DISPLAY=] GROUP=`: Set the active display group of an lcd display. This allows to define multiple display data groups in the config, diff --git a/klippy/extras/tuning_tower.py b/klippy/extras/tuning_tower.py index 0bcfc4db..493db2c8 100644 --- a/klippy/extras/tuning_tower.py +++ b/klippy/extras/tuning_tower.py @@ -28,9 +28,16 @@ class TuningTower: command = gcmd.get('COMMAND') parameter = gcmd.get('PARAMETER') self.start = gcmd.get_float('START', 0.) - self.factor = gcmd.get_float('FACTOR') + self.factor = gcmd.get_float('FACTOR', 0.) self.band = gcmd.get_float('BAND', 0., minval=0.) + self.step_delta = gcmd.get_float('STEP_DELTA', 0.) + self.step_height = gcmd.get_float('STEP_HEIGHT', 0., minval=0.) self.skip = gcmd.get_float('SKIP', 0., minval=0.) + if self.factor and (self.step_height or self.step_delta): + raise gcmd.error( + "Cannot specify both FACTOR and STEP_DELTA/STEP_HEIGHT") + if (self.step_delta != 0.) != (self.step_height != 0.): + raise gcmd.error("Must specify both STEP_DELTA and STEP_HEIGHT") # Enable test mode if self.gcode.is_traditional_gcode(command): self.command_fmt = "%s %s%%.9f" % (command, parameter) @@ -41,8 +48,19 @@ class TuningTower: self.last_z = -99999999.9 self.last_command_value = None self.get_position() - gcmd.respond_info("Starting tuning test (start=%.6f factor=%.6f)" - % (self.start, self.factor)) + message_parts = [] + message_parts.append("start=%.6f" % (self.start,)) + if self.factor: + message_parts.append("factor=%.6f" % (self.factor,)) + if self.band: + message_parts.append("band=%.6f" % (self.band,)) + else: + message_parts.append("step_delta=%.6f" % (self.step_delta,)) + message_parts.append("step_height=%.6f" % (self.step_height,)) + if self.skip: + message_parts.append("skip=%.6f" % (self.skip,)) + gcmd.respond_info( + "Starting tuning test (" + " ".join(message_parts) + ")") def get_position(self): pos = self.normal_transform.get_position() self.last_position = list(pos) @@ -50,6 +68,9 @@ class TuningTower: def calc_value(self, z): if self.skip: z = max(0., z - self.skip) + if self.step_height: + return self.start + \ + self.step_delta * math.floor(z / self.step_height) if self.band: z = (math.floor(z / self.band) + .5) * self.band return self.start + z * self.factor