Наверное редкий владелец принтера Qidi Q2 и подобных с тензодатчиком не сталкивался с проблемой: на кончик сопла налипла капля пластика, датчик из-за неё сработал раньше времени, и в итоге вся карта высот стола (Bed Mesh) “улетела” вверх. Результат — первый слой печатается в воздухе, адгезии ноль, печать испорчена.

Вместо того чтобы надеяться на удачу или бесконечно тереть сопло об щетку, предлагаю добавить простую проверку в стартовый макрос печати.

Идея

Проблема возникает именно из-за наличия тензодатчика (это новация Qidi Q2) и логики подготовки печати. Принтер выполняет “продувку” сопла в корзину, охлаждает сопло до 140 градусов и выполняет пару проходов по силиконовой щетке. Это срабатывает не всегда, иногда на холодном сопле остается капля довольно жесткого пластика при такой температуре. И с таким носом принтер уже едет делать Z_TILT_ADJUST и G29.

Если посмотреть на стартовый скрипт печати Qidi Q2:

PRINT_START
[gcode_macro PRINT_START]
gcode:
    SKEW_PROFILE LOAD=qidi_q2_skew
    AUTOTUNE_SHAPERS
    DISABLE_ALL_SENSOR
    CLEAR_PAUSE
    
    {% set bedtemp = params.get('BED') | int %}
    {% set hotendtemp = params.get('HOTEND') | int %}
    {% set chambertemp = params.get('CHAMBER', 0) | int %}
    {% set extruder = params.EXTRUDER|default(0)|int %}
    {% set Polar_cooler = printer.save_variables.variables.enable_polar_cooler|default(0) %}

    M104 S0
    {% if chambertemp == 0 %}
        M106 P3 S255
    {% endif %}
    M140 S{bedtemp}    
    G28   
    M141 S{chambertemp}    
    SET_GCODE_OFFSET Z=0 MOVE=0
    BUFFER_MONITORING ENABLE=0
    {% if printer.save_variables.variables.box_count >= 1 and printer["box_extras"] %} 
        SAVE_VARIABLE VARIABLE=load_retry_num VALUE=0
        SAVE_VARIABLE VARIABLE=retry_step VALUE=None
        CLEAR_TOOLCHANGE_STATE
        {% for i in range(16) %}
            SAVE_VARIABLE VARIABLE=runout_{i} VALUE=0
            G4 P100
        {% endfor %}
        {% if printer.save_variables.variables.enable_box == 1 %}
            BOX_PRINT_START EXTRUDER={extruder} HOTENDTEMP={hotendtemp}
            M400
            EXTRUSION_AND_FLUSH HOTEND={hotendtemp}
        {% endif %}
    {% endif %}

    CLEAR_NOZZLE HOTEND={hotendtemp}
    #切料调平
    CUT_FILAMENT_1
    M104 S140
    G4 P3000
    M400
    G28    
    Z_TILT_ADJUST

    M104 S140
    M190 S{bedtemp}   
    M191 S{chambertemp}
    M400
    G4 P3000
    
    G29
    G0 Z50 F600
    G0 X260 Y5  F30000
    {% if printer.save_variables.variables.box_count >= 1 and printer["box_extras"] and printer.save_variables.variables.enable_box == 1 %}
        BUFFER_MONITORING ENABLE=1 
    {% endif %}
    M191 S{chambertemp}
    M109 S{hotendtemp}
    M204 S10000
    M106 P4 S{Polar_cooler}                    #根据设置开启空调

    set_zoffset
    ENABLE_ALL_SENSOR
    save_last_file

Видно что единственное куда стоит вмешаться это команда G29 (bed mesh), остальное от смещения по z пострадать не должно, даже Z_TILT_ADJUST отработает корректно. Но после G29 с грязным соплом вся последующая сетка высот стола (kamp) будет иметь положительное смещение.

Реализация защиты

Предлагаю следующий макрос, который после построения сетки вычисляет среднее арифметическое значение Z всех точек. Если оно выше определенного порога, принтер уходит на повторную чистку и переделывает сетку заново. После этого мы повторяем G29 и если повторная сетка высот легла выше порога - выбрасываем алерт и прерываем печать.

  1. Добавьте код макроса _CHECK_NOZZLE_DIRTYв gcode_macro.cfg:

[gcode_macro _CHECK_NOZZLE_DIRTY]
description: Детекция грязного сопла и автоматический повтор очистки
variable_retry_count: 0
gcode:
    {% set profile = params.PROFILE|default('kamp') %}
    {% set hotendtemp = params.HOTEND|default(250)|int %}
    
    # Проверяем наличие профиля сетки в системе
    {% if profile in printer.bed_mesh.profiles %}
        {% set mesh = printer.bed_mesh.profiles[profile].points %}
        {% set total_z = namespace(val=0) %}
        {% set count = namespace(val=0) %}

        # Считаем сумму всех значений Z в сетке
        {% for row in mesh %}
            {% for z in row %}
                {% set total_z.val = total_z.val + z %}
                {% set count.val = count.val + 1 %}
            {% endfor %}
        {% endfor %}

        # Вычисляем средний по Z
        {% if count.val > 0 %}
            {% set avg_z = total_z.val / count.val %}
        {% endif %}

        # Порог 0.07 — мое значение, подберите под себя.
        {% if avg_z > 0.07 %}
            {% if retry_count < 1 %}
                { action_respond_info("ВНИМАНИЕ: Сопло грязное (Z-avg: %.3f). Попытка очистки..." % avg_z) }
                SET_GCODE_VARIABLE MACRO=_CHECK_NOZZLE_DIRTY VARIABLE=retry_count VALUE=1
                
                CLEAR_NOZZLE HOTEND={hotendtemp} # стандартный макрос чистки qidi
                G28 Z
                G29 # повторный замер сетки (получим новые цифры в 'kamp')
            {% else %}
                SET_GCODE_VARIABLE MACRO=_CHECK_NOZZLE_DIRTY VARIABLE=retry_count VALUE=0
                { action_raise_error("ОШИБКА: Повторная чистка не помогла (Z-avg: %.3f). Остановка." % avg_z) }
            {% endif %}
        {% else %}
            { action_respond_info("ПРОВЕРКА: Сопло чистое (Z-avg: %.3f). Печать разрешена." % avg_z) }
            SET_GCODE_VARIABLE MACRO=_CHECK_NOZZLE_DIRTY VARIABLE=retry_count VALUE=0
        {% endif %}
    {% else %}
        { action_respond_info("ПРОВЕРКА: Профиль сетки %s не найден." % profile) }
    {% endif %}
  1. Вставьте вызов макроса в ваш PRINT_START сразу после калибровки стола G29:

# ... подготовка, нагрев ...
G29 ; Калибровка сетки стола
_CHECK_NOZZLE_DIRTY PROFILE=kamp HOTEND={hotendtemp}
# ... продолжение печати ...

Вот так работа макроса выглядит в логах klipper:

...
Mesh Bed Leveling Complete
save_config: set [bed_mesh kamp] version = 1
save_config: set [bed_mesh kamp] points =   0.031094, 0.072891, 0.070781, 0.028594  0.153359, 0.182891, 0.177109, 0.173594  0.212812, 0.222578, 0.060469, 0.208047  0.254922, 0.230703, 0.238828, 0.230625  0.219219, 0.217187, 0.008594, -0.021797  0.143516, 0.169922, 0.005234, -0.037188
save_config: set [bed_mesh kamp] x_count = 4
save_config: set [bed_mesh kamp] y_count = 6
save_config: set [bed_mesh kamp] mesh_x_pps = 2
save_config: set [bed_mesh kamp] mesh_y_pps = 2
save_config: set [bed_mesh kamp] algo = lagrange
save_config: set [bed_mesh kamp] tension = 0.2
save_config: set [bed_mesh kamp] min_x = 60.0
save_config: set [bed_mesh kamp] max_x = 210.0
save_config: set [bed_mesh kamp] min_y = 10.0
save_config: set [bed_mesh kamp] max_y = 260.0
Bed Mesh state has been saved to profile [kamp]
for the current session.  The SAVE_CONFIG command will
update the printer config file and restart the printer.
SAVE_CONFIG to '/home/mks/printer_data/config/printer.cfg' (backup in '/home/mks/printer_data/config/printer-20260412_211059.cfg')
ВНИМАНИЕ: Сопло грязное (Z-avg: 0.136). Попытка очистки №1...
Heater extruder approaching new target of 240.000
...

Совет по настройке: Начните с порога 0.07 - 0.1 мм. Он должен быть выше погрешности вашего датчика и теплового расширения, но меньше высоты первого слоя вашего пластика.

В норме среднее значение Z по сетке после G29 должно быть близким к нулю, с разбросом не более 0.2. Если вы не выполняли калибровку стола, то применяйте макрос аккуратнее - подберите свое пороговое значение. А лучше выполните калибровку стола. Мой порог в 0.07 мм — гарантированно ловит попытки мешинга с грязным носом.

Если есть желание протестировать работу, можно так - подсовывая при каждом замере сложенную в пару слоев бумажку (я проверял щупом 0.1).

Надеюсь это сэкономит Вам кучу времени при удаленном запуске печати, когда нет возможности лично проверить чистоту сопла.

Удачи в печати.

Комментарии (0)