protoloft / klipper_z_calibration

Klipper plugin for self-calibrating z-offset
GNU General Public License v3.0
1.06k stars 152 forks source link

"Offset is greater than allowed": leads to probe not docking, crashing the bed #94

Closed stahlfabrik closed 1 year ago

stahlfabrik commented 1 year ago

Hi,

I upgraded my Voron 2.4 and your plugin to the latest version. Now - I do not why yet, the calibrate_z fails with

"Offset is greater than allowed: offset=1.061 > max_deviation=1.000"

Then the end_gcode seems not to be executed which I think is a bad bug. end_gcode:


#   A list of G-Code commands to run after each calibration command.
#   See docs/Command_Templates.md for the G-Code format. This can be used to
#   detach the probe afterwards.
  Dock_Probe
  _SET_Z_CURRENT

Preferably IMHO the print should be canceled - or the end_gcode should be executed.

stahlfabrik commented 1 year ago

Or is there a way for my print_start gcode to check if calibrate_z was successful and then cancel print on my terms?

stahlfabrik commented 1 year ago

I have configured offset_margins: -1.1,1.1

The values seems to get ignored. The third crash just happened: Offset is greater than allowed: offset=1.069 > max_deviation=1.000

So I have to configure max_deviation still?

This is my current config


nozzle_xy_position: 97,307
#   A X, Y coordinate (e.g. 100,100) of the nozzle, clicking on the z endstop.
switch_xy_position: 93,283
#   A X, Y coordinate (e.g. 100,100) of the probe's switch body, clicking on
#   the z endstop.
#switch_xy_offsets: optional when switch_xy_position is used
#   Instead of an absolute position (switch_xy_position), this configuration
#   adds an X, Y offset (e.g. -6,-18) to the nozzle position.
#bed_xy_position: default from relative_reference_index of bed_mesh
#   A X, Y coordinate (e.g. 100,100) where the print surface (e.g. the center
#   point) is probed. These coordinates are adjusted by the
#   probe's X and Y offsets. The default is the relative_reference_index
#   of the configured bed_mesh, if configured. It's possible to change the relative
#   reference index at runtime or use the GCode argument BED_POSITION of CALIBRATE_Z.
wiggle_xy_offsets: 0,0
#   After probing the nozzle and retracting, move x some distance away and
#   back. Useful to prevent the z endstop pin sticking to the nozzle and
#   being pulled out of the assembly. Can be negative. Defaults to zero to
#   disable it. Can be combined in x and y to move diagonally. Be careful
#   to not move your nozzle out of range!
switch_offset: 0.46
#   The trigger point offset of the used mag-probe switch.
#   A larger value will position the nozzle closer to the bed.
#   This must be determined manually. More on this later
#   in this section..
offset_margins: -1.1,1.1
#   The minimum and maximum margins allowed for the calculated offset.
#   If the offset is outside these values, it will stop!
#   The margin can be defined as "min,max" e.g. "-0.5,1.5" or by just one
#   value e.g. "1.0" which translates to "-1.0,1.0" (which is also the default).
#max_deviation: DEPRECATED - please use offset_margins instead!
#   The maximum allowed deviation of the calculated offset.
#   If the offset exceeds this value, it will stop!
#   The default is 1.0 mm.
#samples: default from "probe:samples" section
#   The number of times to probe each point. The probed z-values
#   will be averaged. The default is from the probe's configuration.
#samples_tolerance: default from "probe:samples_tolerance" section
#   The maximum Z distance (in mm) that a sample may differ from other
#   samples. The default is from the probe's configuration.
#samples_tolerance_retries: default from "probe:samples_tolerance_retries" section
#   The number of times to retry if a sample is found that exceeds
#   samples_tolerance. The default is from the probe's configuration.
#samples_result: default from "probe:samples_result" section
#   The calculation method when sampling more than once - either
#   "median" or "average". The default is from the probe's configuration.
#safe_z_height: 2 * z_offset from the "probe:z_offset" section
#   The absolute z position in mm to move to before moving to the next
#   position. The default is two times the z_offset from the probe's
#   configuration. The minimum safe z height is 3mm.
#clearance: DEPRECATED - please use safe_z_height instead!
#   The distance in mm to move up before moving to the next
#   position. The default is two times the z_offset from the probe's
#   configuration.
#position_min: default from "stepper_z:position_min" section.
#   Minimum valid distance (in mm) used for probing move. The
#   default is from the Z rail configuration.
speed: 200
#   The moving speed in X and Y. The default is 50 mm/s.
#lift_speed: default from "probe:lift_speed" section
#   Speed (in mm/s) of the Z axis when lifting the probe between
#   samples and clearance moves. The default is from the probe's
#   configuration.
#probing_speed: default from "stepper_z:homing_speed" section.
#   The fast probing speed (in mm/s) used, when probing_first_fast
#   is enabled. The default is from the Z rail configuration.
#probing_second_speed: default from "stepper_z:second_homing_speed" section.
#   The slower speed (in mm/s) for probing the recorded samples.
#   The default is second_homing_speed of the Z rail configuration.
#probing_retract_dist: default from "stepper_z:homing_retract_dist" section.
#   Distance to retract (in mm) before probing the next sample.
#   The default is homing_retract_dist from the Z rail configuration.
#probing_first_fast: false
#   If true, the first probing will be faster by the probing speed.
#   This is to get down faster and not record the result as a
#   probing sample. The default is false.
start_gcode:
#   A list of G-Code commands to run before each calibration command.
#   See docs/Command_Templates.md for the G-Code format. This can be used to
#   attach the probe.
  _SET_Z_CURRENT VAL=HOME
  Attach_Probe
#before_switch_gcode:
#   A list of G-Code commands to run before to each probing on the
#   mag-probe. See docs/Command_Templates.md for the G-Code format. This can
#   be used to attach the probe after probing on the nozzle and before probing
#   on the mag-probe.
end_gcode:
#   A list of G-Code commands to run after each calibration command.
#   See docs/Command_Templates.md for the G-Code format. This can be used to
#   detach the probe afterwards.
  Dock_Probe
  _SET_Z_CURRENT```
stahlfabrik commented 1 year ago

Yup, when configuring max_deviation to 1.1 it works... So that variable is not deprecated really but needed very much?

stahlfabrik commented 1 year ago

Mainsail updater says I am on version v1.0.0-0-g73d62dc of z_calibration

stahlfabrik commented 1 year ago

Another (and my last hopefully) input: Does it cancel the current print start gcode when that error is triggered? Because, IMHO the next command (Dock_Probe_Unlock) should have undocked anyway: CALIBRATE_Z Dock_Probe_Unlock

So I think CALIBRATE_Z was erroring, then PRINT_START was exited and Klipper started to print with the probe on...

Havoc340 commented 1 year ago

I was having an issue similar to this. My routine WAS like this:

Home printer (xyz) Quad Gantry Level Auto Z

It would fail with a 2.3mm error.

The problem was that my gantry sags a lot. So when I home the printer the first time, it sets the original Z location. Quad Gantry Level moves the gantry and fixes the sag BUT when it does, the nozzle is now over 2mm higher than it used to be. When I go to do AutoZ next, the distance was out of tolerance.

My fix was to add another home in the routine AFTER QGL, before AutoZ, to reset the Z height with a level gantry. I also did a manual XY to my pin location to be sure not to drag the euclid probe across the bed into the pin. So it now looks like this:

BED_MESH_CLEAR
G28                                                  # initial home 
M117 Quad Gantry Level...              #screen message to tell me what it's doing next  
DEPLOY_PROBE                               #deploy euclid probe
G0 Z20                                            # safe move to clear stuff
G0 Y300                                          # safe move to clear stuff
QUAD_GANTRY_LEVEL_ORIGINIAL
M117 Calibrate Z                            #screen message to tell me what it's doing next  
G0 X341.6 Y419.5                           #safe move to put nozzle above pin again
G28 Z                                             #reset Z home after QGL
CALIBRATE_Z                                 #calibrate Z
M117 Generate Mesh                   #screen message to tell me what it's doing next  
BED_MESH_CALIBRATE                 #run mesh
STOW_PROBE                                #put probe away

I will say that my config is custom built by me and I don't know exactly what I'm doing, but I go this to work. Also my routines are a little modified to keep the probe deployed during QGL, Autoz and the bed mesh, so I only deploy and stow my probe once. 

I do not know if this is your problem you are having, but I had the same error and homing Z after QGL but before calibrate_z is how I fixed it.

TitusLabs commented 1 year ago

I'm sorry or your crash!

But yes, a z homing after QGL helps to keep the offset small. I should have mentioned this in my documentation.

So, if I understand you correctly, the end gcode is not executed, the error is printed and the printer continues to print?

I can't quite understand that. At this point the code is as it has always been. If the offset is out of the configured range, the end gcode is executed and an error is raised. This should stop the print and it always have in my case :thinking:

Is your clearance/safe_z_height configured correctly? Or what exactly is your move for?

stahlfabrik commented 1 year ago

I do a Z homing after QGL. Mechanically, the thing that is different now than when I set up auto calibrate z plugin is that I use a different PEI sheet - so I guess there is the root cause for me getting now a different offset.

So yes, the end gcode is not executed, when the offset is bigger than the max_deviation. So the klicky probe is not getting docked and the print starts immediately - I even think that the rest of my start_print gcode is also not executed. Because I think in the end Dock_Probe_Unlock should have docked the probe as well, right?

So if you want to experience my issue - I would think you would have to configure max_deviation to be smaller than the offset and see thing go downhill:-)

Another point I wanted to underline: if I do not configure max_deviation to be 1.1 (but comment max_deviation out completely, your plugin thinks it is 1.0 - even though I configured the offset_margins: -1.1,1.1 I read the available information as if the offset_margins would be used, if max_deviation is not configured. And max_deviation to be obsolete. But to me it seems that this ist not working as expected.

As my print_start macro is a little fancy I did not want to post it here. But I do now, so you can understand better what I do. Maybe the delayed gcode business leads to the print to start even when the plugin errors? I do not know...

[gcode_macro PRINT_START]
description: All commands needed at print start
variable_bed_target: 0.0
variable_extruder_target: 0.0
variable_chamber_target: 0.0
variable_wait_time: 0.0
variable_extra_wait_time: 0.0
variable_min_rate: 0.0
variable_z_adjust: 0.0
variable_wait_anyway: False

## Internal variables
# state in ['initialize', 'heat_bed', 'wait', 'heat_extra', 'wait_extra', 'perform_remaining_actions']
variable_state: 'initialize'
variable_heat_bed_report_interval: 0
variable_wait_report_interval: 0
variable_total_time_elapsed: 0
variable_timing_interval: 0
variable_heat_to_bed_temp: 0.0
variable_temp_history: None
variable_smoothed_temp_history: None
variable_temp_smooth_time: 0.0
variable_rate_smooth_time: 0.0
variable_current_slope: None
variable_current_bed_temp: 0.0
variable_current_chamber_temp: 0.0
variable_cancel_wait: False
variable_cancel_extra_wait: False
variable_bed_temp_trigger_wait_threshhold: 0.0
variable_bed_temp_skip_wait_threshhold: 0.0

gcode:
  {% set ps = printer['gcode_macro PRINT_START'] %}
  {% set user = printer['gcode_macro _USER_VARIABLE'] %}
  {% set current_bed_temp = printer.heater_bed.temperature|float|round(1) %}
  {% set current_chamber_temp = printer["temperature_fan chamber"].temperature|float|round(1)%}

  SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=current_bed_temp VALUE={current_bed_temp}
  SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=current_chamber_temp VALUE={current_chamber_temp}

  {% if state == 'initialize' %}
    {action_respond_info("PRINT_START state: 'initialize'")}
    ## Store params
    #  BED_TEMP        : Target temperature for the Bed. Is also used to decide 
    #                    if heatsoak is needed
    #  EXTRUDER_TEMP   : Target temperature for the Extruder
    #  CHAMBER_TEMP    : Target temperature for the chamber fan controll
    #  MIN_RATE        : Chamber temp/min rate that is still considered worth waiting
    #  WAIT_TIME       : Max time to wait wail chamber is warming up / soaking
    #  EXTRA_WAIT_TIME : Time to wait if no chamber soak is done or to wait to bed to 
    #                    stabilize to final target temperature after chamber soak
    #  Z_ADJUST        : Add extra z offset via slicer

    {% set bed_target = params.BED_TEMP | default(printer.heater_bed.target, true) | float %}
    {% set extruder_target = params.EXTRUDER_TEMP | default(printer.extruder.target, true) | float %}
    {% set chamber_target = params.CHAMBER_TEMP | default(40) | float %}
    {% set min_rate = params.MIN_RATE | default(0.3) | float %}
    {% set wait_time = params.WAIT_TIME | default(45) | float %}
    {% set extra_wait_time = params.EXTRA_WAIT_TIME | default(5) | float %}
    {% set z_adjust = params.Z_ADJUST | default(0.0) | float %}
    {% set wait_anyway = params.WAIT_ANYWAY|default('false')|lower == 'true'%}

    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=bed_target VALUE={bed_target}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=extruder_target VALUE={extruder_target}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=chamber_target VALUE={chamber_target}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=min_rate VALUE={min_rate}

    #internal
    {% set timing_interval = 1 %}
    {% set heat_bed_report_interval = 10 %}
    {% set wait_report_interval = 20 %}
    {% set temp_smooth_time = 4 %} ## seconds for temp smoothing
    {% set rate_smooth_time = 30 %} ## seconds for rate smoothing
    {% set cancel_wait = False %}
    {% set cancel_extra_wait = False %}
    {% set bed_temp_trigger_wait_threshhold = 90.0 %}
    {% set bed_temp_skip_wait_threshhold = 5.0 %}

    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=temp_history VALUE="{[current_chamber_temp] | pprint}"
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=smoothed_temp_history VALUE="{[] | pprint}"
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE=0
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=current_slope VALUE=None
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=timing_interval VALUE={timing_interval}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=heat_bed_report_interval VALUE={heat_bed_report_interval}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=wait_report_interval VALUE={wait_report_interval}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=temp_smooth_time VALUE={temp_smooth_time}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=rate_smooth_time VALUE={rate_smooth_time}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=cancel_wait VALUE={cancel_wait}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=cancel_extra_wait VALUE={cancel_extra_wait}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=bed_temp_trigger_wait_threshhold VALUE={bed_temp_trigger_wait_threshhold}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=bed_temp_skip_wait_threshhold VALUE={bed_temp_skip_wait_threshhold}

    {% if (bed_target > bed_temp_trigger_wait_threshhold) or wait_anyway %}
    # We want a heated chamber
      {% set max_safe_bed_temp = printer.configfile.settings.heater_bed.max_temp|float|round(1) - 5.0 %}
      {% set heat_to_bed_temp = [max_safe_bed_temp, bed_target]|max %}
    {% else %}
      {% set heat_to_bed_temp = bed_target %}
      {% set wait_time = 0 %}
    {% endif %}

    {% if (current_bed_temp - bed_target)|abs < bed_temp_skip_wait_threshhold %}
      {action_respond_info("Initial bed temp %.1f°C already near (<%.1f°C) target %.1f°C. Skipping wait." % (current_bed_temp, bed_temp_skip_wait_threshhold, bed_target))}
      {% set heat_to_bed_temp = bed_target %}
      {% set wait_time = 0 %}
      {% set extra_wait_time = 0 %}
    {% else %}
      {action_respond_info("Initial bed temp %.1f°C. Bed target %.1f°C. Heating now to %.1f°C" % (current_bed_temp, bed_target, heat_to_bed_temp))}
      {action_respond_info("Waiting %dmin at max for chamber to heat up to %.1f°C after bed has reached temp." % (wait_time, chamber_target))}
      {action_respond_info("Stop wait immediately when chamber temp rate increase is below %.1f°C/s" % min_rate)}
      {action_respond_info("Then wait another %dmin after bed has reached its final temperature" % extra_wait_time)}
    {% endif %}

    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=heat_to_bed_temp VALUE={heat_to_bed_temp}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=wait_time VALUE={wait_time * 60}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=extra_wait_time VALUE={extra_wait_time * 60}

    # Turn on case light LEDs
    _CASELIGHT_ON
    # Blink the LCD Knob red
    _LCD_KNOB COLOR=RED BLINK=1
    # Turn off exhaust fans
    M141 S0
    # Clear pause state
    CLEAR_PAUSE
    # Clear bed mesh
    BED_MESH_CLEAR
    # Delete Z Offset
    SET_GCODE_OFFSET Z=0
    # Set feedrate to 100%
    M220 S100
    # Set flow to 100%
    M221 S100
    # Metric values
    G21
    # Absolute positioning
    G90 
    # set extruder to relative mode
    M83

    # Start bed heating
    STATUS_HEATING
    M140 S{heat_to_bed_temp}
    # Start part cooling fan
    M106 S90

    # Home if needed
    _CG28
    # Park Toolhead higher
    G0 Z{user.park_center_z} F{user.speed_z_hop}
    G0 X{user.park_center_x} Y{user.park_center_y} F{user.speed_travel}

    PAUSE_BASE
    SET_GCODE_VARIABLE MACRO=CANCEL_PRINT VARIABLE=execute VALUE=False
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"heat_bed"'
    UPDATE_DELAYED_GCODE ID=_PRINT_START_HELPER DURATION={timing_interval}

  {% elif state == 'heat_bed' %}
    {% if ((ps.current_bed_temp - ps.heat_to_bed_temp)|abs < 0.5) or cancel_wait %}
      {action_respond_info("Bed reached %.1f°C in %d:%02d" % (ps.heat_to_bed_temp, ps.total_time_elapsed|int // 60, ps.total_time_elapsed|int % 60))}
      {action_respond_info("Switching state to 'wait'")}
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE=0
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"wait"'
    {% endif %}

    UPDATE_DELAYED_GCODE ID=_PRINT_START_HELPER DURATION={timing_interval}

  {% elif state == 'wait' %}
    {% set rate_not_achieved = (ps.current_slope < ps.min_rate) if ps.current_slope is not none else False%}
    {% set wait_expired = ps.total_time_elapsed >= ps.wait_time %}
    {% set chamber_reached_target = ps.current_chamber_temp >= ps.chamber_target %}

    {% if rate_not_achieved%}
      {action_respond_info("Minimum chamber heating rate not achieved. Rate %.1f°C/s" %ps.current_slope)}   
    {% endif %}

    {% if wait_expired %}
      {action_respond_info("Wait time has expired")}   
    {% endif %}

    {% if chamber_reached_target %}
      {action_respond_info("Chamber has reached target temp")}   
    {% endif %}

    {% if rate_not_achieved or wait_expired or chamber_reached_target or ps.cancel_wait%}
      M140 S{ps.bed_target}
      {action_respond_info("Waited for %d:%02d" % (ps.total_time_elapsed|int // 60, ps.total_time_elapsed|int % 60))}
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE=0 

      {% if ps.extra_wait_time > 0 %}
        {action_respond_info("Switching state to 'heat_extra'")}
        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"heat_extra"'
      {% else %}
        {action_respond_info("Switching state to 'perform_remaining_actions'")}
        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"perform_remaining_actions"'
      {% endif%}
    {% endif %}
    UPDATE_DELAYED_GCODE ID=_PRINT_START_HELPER DURATION={timing_interval}

  {% elif state == 'heat_extra' %}
    {% if (ps.current_bed_temp - ps.bed_target)|abs < 0.5 %}
      {action_respond_info("Bed reached %.1f°C in %d:%02d" % (ps.bed_target, ps.total_time_elapsed|int // 60, ps.total_time_elapsed|int % 60))}
      {action_respond_info("Switching state to 'wait_extra'")}
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE=0
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"wait_extra"'
    {% endif %}
    UPDATE_DELAYED_GCODE ID=_PRINT_START_HELPER DURATION={timing_interval}
  {% elif state == 'wait_extra' %}
    {% set wait_expired = ps.total_time_elapsed >= ps.extra_wait_time %}
    {% if wait_expired or ps.cancel_extra_wait%}
      {action_respond_info("Waited for %d:%02d" % (ps.total_time_elapsed|int // 60, ps.total_time_elapsed|int % 60))}
      {action_respond_info("Switching state to 'perform_remaining_actions'")}
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE=0 
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"perform_remaining_actions"'
    {% endif %}
    UPDATE_DELAYED_GCODE ID=_PRINT_START_HELPER DURATION={timing_interval}

  {% elif state == 'perform_remaining_actions' %}
    RESUME_BASE
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"initialize"'
    _LCD_KNOB COLOR=RED
    # Heat up and wait for extruder
    M117 Heat extruder
    {action_respond_info("Heat extruder")}
    M109 S{ps.extruder_target}
    # Turn off part cooling fan
    M107

    Attach_Probe_Lock
    M117 QGLing...
    {action_respond_info("Quad gantry leveling...")}
    QUAD_GANTRY_LEVEL
    M117 Homing...
    {action_respond_info("Homing...")}
    G28 Z

    M117 Bed mesh leveling...
    {action_respond_info("Bed mesh leveling...")}
    BED_MESH_CALIBRATE
    CLEAN_NOZZLE_NO_PURGE
    CALIBRATE_Z
    Dock_Probe_Unlock

    SET_GCODE_OFFSET Z_ADJUST={ps.z_adjust} MOVE=1

    # Set target temp for exhaust fan
    M141 S{ps.chamber_target}

    STATUS_PRINTING
    M117 Prime Line...
    {action_respond_info("Prime Line...")}
    LINE_PURGE
    M117 Printing...
    {action_respond_info("Printing...")}
    G92 E0
    # Metric values
    G21
    # Absolute positioning
    G90 
    # set extruder to relative mode
    M83
    UPDATE_DELAYED_GCODE ID=_CLEAR_DISPLAY DURATION=1
  {% endif %}

[gcode_macro CANCEL_WAIT]
description: Cancel the waiting phase in which the chamber gets heat soaked
gcode:
  {action_respond_info("Canceling PRINT_START wait")}
  SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=cancel_wait VALUE='True'

[gcode_macro CANCEL_EXTRA_WAIT]
description: Cancel the waiting phase in which the bed stabilizes to its target temperature
gcode:
  {action_respond_info("Canceling PRINT_START extra_wait")}
  SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=cancel_extra_wait VALUE='True'

[delayed_gcode _PRINT_START_HELPER]
  gcode:
    {% set ps = printer['gcode_macro PRINT_START'] %}
    {% set state = ps.state %}

    # update total time elapsed
    {% set total_time_elapsed = ps.total_time_elapsed + ps.timing_interval %}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=total_time_elapsed VALUE={ total_time_elapsed }

    # compute the new temp difference and save history
    {% set temp_history = ps.temp_history %}
    {% set smoothed_temp_history = ps.smoothed_temp_history %}
    {% set temp_diff = ps.current_chamber_temp - (temp_history | last) %}
    {% set _ = temp_history.append(ps.current_chamber_temp) %}
    {% set chamber_temp_smoothed = None %}
    {% set slope = None %}
    {% if (temp_history | length) > ps.temp_smooth_time %}
        {% set temp_history = temp_history[1:] %}
        # compute average temp
        {% set chamber_temp_smoothed = ((temp_history | sum) / (temp_history | length)) %}
        # save raw value to history
        {% set _ = smoothed_temp_history.append(chamber_temp_smoothed) %}
        # round off for display and comparisons later
        {% set chamber_temp_smoothed = chamber_temp_smoothed | round(3) %}
        # compute the slope
        {% if (smoothed_temp_history | length) > ps.rate_smooth_time %}
            {% set smoothed_temp_history = smoothed_temp_history[1:] %}
            # Least Squares 
            # adapted from: https://towardsdatascience.com/linear-regression-using-least-squares-a4c3456e8570
            # X values are time in seconds
            # Y values are temperatures
            {% set count = (smoothed_temp_history | length) %}
            {% set times = range(0, count, 1) %}
            {% set x_sum = (times | sum) | float %}
            {% set y_sum = (smoothed_temp_history | sum) | float %}
            # Squares
            # Jinja oddity: += doesn't work in loops??, so collect squares and sum after
            {% set xx_sum_arr = [] %}
            {% set xy_sum_arr = [] %}
            {% for i in times %}
                {% set x = times[i] %}
                {% set y = smoothed_temp_history[i] %}
                {% set _ = xx_sum_arr.append(x * x) %}
                {% set _ = xy_sum_arr.append(x * y) %}
            {% endfor %}
            {% set xx_sum = (xx_sum_arr | sum) | float %}
            {% set xy_sum = (xy_sum_arr | sum) | float %}
            # Slope calculation. Slope is per second so * 60 for rate per minute
            {% set slope = (60.0 * ((count | float * xy_sum) - (x_sum * y_sum)) / ((count | float * xx_sum) - (x_sum * x_sum))) | round(3) %}
            SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=current_slope VALUE={slope}
        {% endif %}
    {% endif %}
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=temp_history VALUE="{(temp_history | pprint | replace("\n", ""))}"
    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=smoothed_temp_history VALUE="{(smoothed_temp_history | pprint | replace("\n", ""))}"

    {% if state == "heat_bed"%}
      M117 Heat bed {(total_time_elapsed|int // 60)}:{'%02d' % (total_time_elapsed|int % 60)}
      {% set msg = "Heating bed - current %.1f°C target %.1f°C" %(ps.current_bed_temp, ps.heat_to_bed_temp) %}
      {% if (total_time_elapsed % ps.heat_bed_report_interval == 0) or (total_time_elapsed - ps.timing_interval == 0) %}
        {action_respond_info("%s" % msg)}
      {% endif %}
    {% endif %}

    {% if state == "wait" %}
      M117 {((ps.wait_time - total_time_elapsed)|int // 60)}:{'%02d' % ((ps.wait_time - total_time_elapsed)|int % 60)} {'%.1f' %ps.current_chamber_temp} {("%.1f" % ps.current_slope) if ps.current_slope is not none else "N/A"}
      {% set msg = "Waiting - bed %.1f°C chamber %.1f°C remaining %d:%02d rate %s" %(ps.current_bed_temp, ps.current_chamber_temp, (ps.wait_time - total_time_elapsed)|int // 60, (ps.wait_time - total_time_elapsed)|int % 60, ("%.1f°C/s" % ps.current_slope) if ps.current_slope is not none else "N/A") %}
      {% if (total_time_elapsed % ps.wait_report_interval == 0) or (total_time_elapsed - ps.timing_interval == 0) %}
        {action_respond_info("%s" % msg)}
      {% endif %}
    {% endif %}

    {% if state == "heat_extra"%}
      M117 Heat extra {(total_time_elapsed|int // 60)}:{'%02d' % (total_time_elapsed|int % 60)}
      {% set msg = "Heating bed extra - current %.1f°C target %.1f°C" %(ps.current_bed_temp, ps.bed_target) %}
      {% if (total_time_elapsed % ps.heat_bed_report_interval == 0) or (total_time_elapsed - ps.timing_interval == 0) %}
        {action_respond_info("%s" % msg)}
      {% endif %}
    {% endif %}

    {% if state == "wait_extra" %}
      M117 Wait extra {((ps.extra_wait_time - total_time_elapsed)|int // 60)}:{'%02d' % ((ps.extra_wait_time - total_time_elapsed)|int % 60)} 
      {% set msg = "Waiting extra - remaining %d:%02d " %((ps.extra_wait_time - total_time_elapsed)|int // 60, (ps.extra_wait_time - total_time_elapsed)|int % 60) %}
      {% if (total_time_elapsed % ps.wait_report_interval == 0) or (total_time_elapsed - ps.timing_interval == 0)%}
        {action_respond_info("%s" % msg)}
      {% endif %}
    {% endif %}

    # Check CANCLE_PRINT was executed
    {% if printer['gcode_macro CANCEL_PRINT'].execute|lower == 'false' %}
      # Continue
      PRINT_START
    {% else %}
      # CANCLE_PRINT was executed
      {action_respond_info("PRINT_START canceled by CANCEL_PRINT")}
      SET_GCODE_VARIABLE MACRO=CANCEL_PRINT VARIABLE=execute VALUE=False
      SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=state VALUE='"initialize"'
      UPDATE_DELAYED_GCODE ID=_CLEAR_DISPLAY DURATION=1
    {% endif %}
TitusLabs commented 1 year ago

I have just tested it again and it docks the probe using the end_gcode, raises the error and stops the print.

Your PRINT_START macro is really complicated. I don't know if this would cause the problem. I cannot do more than throw an error. But never the less, it should execute the end_gcode before raising the error!

TitusLabs commented 1 year ago

I have released a bugfix which should eliminate the max_deviation error if configured properly. But, you should find out why your print does not stop...