Авто-калибровка Pressure Advance тензодатчиком
Если в тулхеде есть датчик силы (load cell — как зонд у Prusa Nextruder, QIDI Q2, машин с Mellow ALPS), им можно мерить противодавление расплава в сопле и подбирать Pressure Advance автоматически, без печати тестовых узоров и разглядывания линий. Родословная метода: Snapmaker U1 (геометрия движения в воздухе) → markniu bd_pressure (step-response разбор) → CNCKitchen PrusaPATuner (эталон для Prusa, июль 2026) → порты под Klipper (KAPAT, autopa — оба AGPL-3.0).
Физика
Давление в зоне плавления — инерционное звено первого порядка: при скачке скорости подачи сила на сопле нарастает/спадает с постоянной времени расплава τ ≈ 30–50 мс для PLA/PETG на direct drive; численно τ близка к оптимальному K (метод «decay» у autopa прямо фитит экспоненту спада и отдаёт τ как K — на их стенде sweep и decay сошлись: PLA 0.033/0.031, PETG 0.034/0.030). Идеально подобранный PA заставляет силу точно следовать командной ступеньке: без заброса (overshoot), недолива (undershoot) и хвоста после остановки.
Сигнал большой: на 24-битном АЦП (gain 128) экструзия 12 мм³/с даёт дельту ~100–130 тыс. отсчётов при шуме покоя σ≈100–800 отсчётов — SNR>120. Таймлайн с моего принтера, ступени 0.83↔5 мм/с (значения датчика, направление «давление = вниз»): базлайн −866k → медленная полка −867k (еле видно, ~1–2k) → быстрая −963k…−994k → после остановки экспоненциальная релаксация к −874k за 4–8 с.
Метод свипа
- Экструзия в воздух асимметричной квадратной волной потока. Дефолты autopa (валидированы на ADS131M02 ~488 Гц): медленная полка VFR_LOW=2 мм³/с × 1.0 с, быстрая VFR=18 мм³/с × 0.25 с, 8 циклов на K, сетка K 0.01–0.08 шагом 0.01, prime 20 мм до, retract 6 мм после, guard 400 мм филамента. На медленном датчике (~40 Гц) ступени удлиняют: tfast 0.5 с, 10 циклов — вдвое больше сэмплов на сегмент. Расход: ~49 мм филамента на одно K при удлинённой геометрии (узкая сетка из 4 K ≈ 250 мм ≈ 0.6 г PLA, полная из 8 K ≈ 450 мм).
- Перед каждым K —
SET_PRESSURE_ADVANCE ADVANCE=<k>; первый цикл после смены K несёт давление прежнего K и исключается из анализа (межсеточных пауз нет сознательно: пауза релаксирует давление и портит первый цикл ещё сильнее). - Каждый цикл разбирается на области (базлайн, фронт, заброс, полка, спад, недолив, хвост восстановления) — считается ~14 метрик: rise/fall_delay, rise/fall_error_area (площади ошибок, np.trapezoid), overshoot (пик − полка − поправка на максимум шума σ·√(2·ln n), НЕ клампить в ноль — кламп цензурирует распределение ровно у K_opt), undershoot, plateau_slope (ползучесть полки), tail_area, settling_time (3σ на 0.1 с).
- Метрики агрегируются медианой по циклам каждого K, нормируются по сетке (p90 модулей), складываются во взвешенную стоимость. Веса эталона: overshoot 2.0, undershoot 2.0, rise_error_area 1.0, fall_error_area/tail_area 1.0, rise/fall_delay 1.0, plateau_slope 0.5, settling_time 0.5. K_opt = минимум долины стоимости (argmin с параболической интерполяцией между точками сетки). Отдельные метрики монотонны по K (overshoot растёт с K, undershoot у малых K) — долину образует только взвешенная сумма, «чинить» монотонную метрику не надо.
Долина с моего PETG (полная сетка, @240, ~40 Гц)
K segs overshoot undershoot
0.0100 10/10 0.0 0.0
0.0300 10/10 0.0 0.0
0.0400 10/10 4092.1 23899.8
0.0500 10/10 12302.9 29742.0
0.0600 10/10 42917.9 41701.5
0.0800 10/10 15605.2 40754.0
→ Sweep K_opt = 0.0589
Обязательный XY-вобл
Klipper применяет PA только к ходам с движением X или Y — в kinematics/extruder.py: can_pressure_advance = axis_r > 0 and (axes_d[0] or axes_d[1]). Чистая E-экструзия меряет НИЧЕГО: при любом K движение идентично, метрики — чистый шум. Поэтому каждая полка — композитный ход G1 <ось><база±0.05> E<объём> F<...>: вобл 0.05 мм включает гейт, физически не двигая голову (0.05–0.2 мм/с). Медленные полки идут в база+вобл, быстрые возвращаются в базу — каждый переход это реверс оси, гейт гарантированно взводится. Marlin/Buddy — тот же класс гейта (planner: use_advance_lead от steps.a||steps.b), PrusaPATuner вобляет 0.4 мм.
Проверка, что PA вообще применяется (смок перед доверием методу): два мини-свипа с K=0 и K=0.05 обязаны дать радикально разные метрики. У меня: K=0 → overshoot 0.0 / undershoot 223; K=0.05 → 23141.8 / 27028.2 — два порядка. Если кривые идентичны — гейт не взводится (вобл нулевой или ось не хоумлена).
Каверза композитного хода: Klipper проверяет max_extrude_cross_section (большое E на крошечное XY = высокий extrude-ratio) — может понадобиться поднять до ~200. E-ускорение фронта определяется accel тулхеда × extrude-ratio (axis_r ~40 при вобле 0.05): даже accel 1000 даёт субмиллисекундную ступень E-скорости — резкости хватает (Prusa на чистом E пришлось задирать E-accel до 5000: на 200 мм/с² эффект PA был ниже шума, R²≈0).
Границы циклов — из планировщика, не из сигнала
Внутри Klipper точное время каждого перехода известно заранее: toolhead.get_last_move_time() и toolhead.register_lookahead_callback(lambda pt: ...) отдают print_time — тот же час, которым штампуются сэмплы датчика. Весь слой «найти свип в записи по активности силы» (~1300 строк у PrusaPATuner, слушающего UDP извне) в Klipper-порте структурно не нужен — KAPAT это доказал и не портировал вовсе.
Гейты качества сегментов (и их подгонка под медленный датчик)
Эталонные гейты autopa/PrusaPATuner, из-за которых сегмент бракуется:
- < 20 сэмплов в окне сегмента;
- частота внутри сегмента < 40 Гц;
- базлайн-окно уже 4 сэмплов;
- фронт < 3× шума базлайна; шум > 30% дельты полок;
- dropout в критической зоне; < 4 зачётных сегментов на K → K выпадает из стоимости.
На датчике ~40 Гц стоковые пороги бракуют 100% данных (мой факт: 0/88 сегментов, K_opt=None). Пороги надо выносить в конфиг и ставить с запасом ПОД фактическую частоту (35 Гц / 12 сэмплов при фактических 38.7 Гц) — и компенсировать удлинёнными ступенями.
Требования к данным
- Единицы не важны: анализ работает от сырых отсчётов, форс = −(counts − tare) («давление → больше»). Калибровка в граммы — косметика.
- Тарирование на каждый запуск (медиана 2–3 с покоя): базлайн плывёт с температурой головы — мой замер: ~50 тыс. отсчётов между холодной и горячей (−918k ↔ −866k).
- Частота выборки — главный ресурс. Замерено прореживанием эталонных записей 488 Гц (bin-усреднение, потом полный анализ):
| Частота | PLA (эталон 0.0328) | PETG (эталон 0.0335) |
|---|---|---|
| 488 Гц | 0.0328 | 0.0335 |
| 200 Гц | 0.0316 (−3.7%) | 0.0332 (−0.9%) |
| 100 Гц | 0.0299 (−8.8%) | 0.0341 (+1.8%) |
| 60 Гц | 0.0308 (−6.1%) | 0.0400 (+19.4%) |
| 38.7 Гц | 0.0274 (−16.5%) | 0.0270 (−19.4%) |
Вывод: 100–200 Гц — комфорт (≤9%), ниже 60 Гц оценка не смещена стабильно, а нестабильна (±20% с переменой знака). На ~40 Гц метод работает — у меня три прогона дали 0.0328/0.0311/0.0331, разброс 6.2% — но абсолют стоит якорить сверкой с ручным методом линий (сошлось: 0.0328 авто ↔ 0.032 руками).
- Заброс/недолив — транзиенты 50–100 мс: на 40 Гц это 2–4 сэмпла; веса смещать к площадным метрикам (интегральные, деградируют мягче).
- Метод decay (τ спада = K) на 40 Гц неприменим: τ≈0.03–0.05 с, окно фита 0.14 с — ~5 сэмплов на всю кривую. Нужно ≥400 Гц.
Загрязнение и ложные результаты
Примеры порчи замера с моей машины (подробно — Загрязнение силовых замеров экструзии):
- куча пластика доросла до сопла → K=0.0407 против чистых 0.031–0.033 (+25%);
- смена материала без продувки: хвост PETG в расплаве завысил K PLA до 0.0366 (+14%);
- экструзия на чистящий ролик → сегменты старших K загрязнены контактом. Симптом «flat table» (метрики не зависят от K) — перепутан знак силы или мёртвый гейт PA.
Практика на конкретной машине — Авто-калибровка PA и потока на QIDI Q2 — гайд. Смежный замер тем же датчиком — Замер максимального объёмного потока тензодатчиком.
Источники
- CNCKitchen/PrusaPATuner — эталон: 5 независимых оценщиков (bd step-response, фазовая кросс-корреляция, интегральная площадь, Theil-Sen по знаковой площади спада, пер-сегментный K_true ≈ K_set + fall_area/amplitude), UDP-метрики Buddy ~180 Гц
- G0BL1N/autopa — Klipper-extra, numpy-порт bd-пути + метод decay; потребляет всего 4 метода Collector-API мейнлайнового load_cell
- vzagranichnyy/KAPAT — порт PrusaPATuner под Klipper (Mellow ALPS/ADS131M02), CNCKitchen ссылается на него официально
- markniu/bd_pressure — происхождение разбора
- Отрицательные результаты: PA через StallGuard TMC2209 не работает (justinh-rahb/TMC-AutoPA: отклонения <0.6% и немонотонны на 5× диапазоне PA — сигнала нет); сенсор-фьюжн с акселерометром не улучшает K (incendiumendy/AutoPA: accel — только диагностика)